Upload
matt-warren
View
542
Download
4
Embed Size (px)
Citation preview
Why?
Save money
Save power
Bad perf == broken
Lost customers
Half a second delay caused a 20% drop in traffic (Google)
Why?
“The most amazing achievement of the computer software industry is its continuing cancellation of the steady and staggering gains made by the computer hardware industry.”
- Henry Petroski
Why?
“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.“
- Donald Knuth
Why?
“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.“
- Donald Knuth
https://blogs.msdn.microsoft.com/bharry/2016/03/28/introducing-application-analytics/
Application Insights Analytics
When?
In production
You won't see ANY perf issues during unit tests
You won't see ALL perf issues in Development
How?
“The simple act of putting a render time in the upper right hand corner of every page we serve forced us to fix all our performance regressions and omissions.”
using BenchmarkDotNet.Attributes;using BenchmarkDotNet.Running;
static Uri @object = new Uri("http://google.com/search");
[Benchmark(Baseline = true)]public string RegularPropertyCall(){
return @object.Host;}
[Benchmark]public object Reflection(){
Type @class = @object.GetType();PropertyInfo property =
@class.GetProperty(propertyName, bindingFlags);return property.GetValue(@object);
}
static void Main(string[] args){
var summary = BenchmarkRunner.Run<Program>();}
Compared to one second
• Millisecond – ms
– thousandth (0.001 or 1/1000)
• Microsecond - μs
–millionth (0.000001 or 1/1,000,000)
• Nanosecond - ns
–billionth (0.000000001 or 1/1,000,000,000)
BenchmarkDotNet
BenchmarkDotNet=v0.9.4.0
OS=Microsoft Windows NT 6.1.7601 Service Pack 1
Processor=Intel(R) Core(TM) i7-4800MQ CPU @ 2.70GHz, ProcessorCount=8
HostCLR=MS.NET 4.0.30319.42000, Arch=32-bit RELEASE
JitModules=clrjit-v4.6.100.0
Type=Program Mode=Throughput
Method | Median | StdDev | Scaled |
--------------------- |------------ |----------- |------- |
RegularPropertyCall |
Reflection |
BenchmarkDotNet
BenchmarkDotNet=v0.9.4.0
OS=Microsoft Windows NT 6.1.7601 Service Pack 1
Processor=Intel(R) Core(TM) i7-4800MQ CPU @ 2.70GHz, ProcessorCount=8
HostCLR=MS.NET 4.0.30319.42000, Arch=32-bit RELEASE
JitModules=clrjit-v4.6.100.0
Type=Program Mode=Throughput
Method | Median | StdDev | Scaled |
--------------------- |------------ |----------- |------- |
RegularPropertyCall | 13.4053 ns | 1.5826 ns | 1.00 |
Reflection | 232.7240 ns | 32.0018 ns | 17.36 |
[Params(1, 2, 3, 4, 5, 10, 100, 1000)]public int Loops;
[Benchmark]public string StringConcat(){
string result = string.Empty;for (int i = 0; i < Loops; ++i)
result = string.Concat(result, i.ToString());return result;
}
[Benchmark]public string StringBuilder(){
StringBuilder sb = new StringBuilder(string.Empty);for (int i = 0; i < Loops; ++i)
sb.Append(i.ToString());return sb.ToString();
}
https://github.com/dotnet/roslyn/issues/5388
How?
Garbage Collection (GC)
Allocations are cheap, but cleaning up isn’t
Difficult to measure the impact of GC
https://samsaffron.com/archive/2011/10/28/in-managed-code-we-trust-our-recent-battles-with-the-net-garbage-collector
Stack Overflow Performance Lessons
Use static classes
Don’t be afraid to write your own tools
Dapper, Jil, MiniProfiler,
Intimately know your platform - CLR
Roslyn Performance Lessons 1
public class Logger{
public static void WriteLine(string s) { /*...*/ }}
public class Logger{
public void Log(int id, int size){
var s = string.Format("{0}:{1}", id, size);Logger.WriteLine(s);
}}
Essential Truths Everyone Should Know about Performance in a Large Managed Codebase
http://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/DEV-B333
Roslyn Performance Lessons 1
public class Logger{
public static void WriteLine(string s) { /*...*/ }}
public class BoxingExample{
public void Log(int id, int size){
var s = string.Format("{0}:{1}", id.ToString(), size.ToString());
Logger.WriteLine(s);}
}
https://github.com/dotnet/roslyn/pull/415
AVOID BOXING
Roslyn Performance Lessons 2class Symbol {
public string Name { get; private set; }/*...*/
}
class Compiler {private List<Symbol> symbols;public Symbol FindMatchingSymbol(string name){
return symbols.FirstOrDefault(s => s.Name == name);}
}
Roslyn Performance Lessons 2class Symbol {
public string Name { get; private set; }/*...*/
}
class Compiler {private List<Symbol> symbols;public Symbol FindMatchingSymbol(string name){
foreach (Symbol s in symbols){
if (s.Name == name)return s;
}
return null;}
}
DON’T USE LINQ
BenchmarkDotNetBenchmarkDotNet=v0.9.4.0
OS=Microsoft Windows NT 6.1.7601 Service Pack 1
Processor=Intel(R) Core(TM) i7-4800MQ CPU @ 2.70GHz, ProcessorCount=8
Frequency=2630654 ticks, Resolution=380.1336 ns, Timer=TSC
HostCLR=MS.NET 4.0.30319.42000, Arch=32-bit RELEASE
JitModules=clrjit-v4.6.100.0
Type=Program Mode=Throughput Runtime=Clr
Method | Median | StdDev | Gen 0 | Bytes Allocated/Op |
---------- |----------- |---------- |------- |------------------- |
Iterative | 39.0957 ns | 0.2150 ns | - | 0.00 |
LINQ | 53.2441 ns | 0.5385 ns | 701.50 | 23.21 |
Roslyn Performance Lessons 3public class Example{
// Constructs a name like "Foo<T1, T2, T3>"public string GenerateFullTypeName(string name, int arity){
StringBuilder sb = new StringBuilder();sb.Append(name);if (arity != 0){
sb.Append("<");for (int i = 1; i < arity; i++){
sb.Append('T'); sb.Append(i.ToString());}sb.Append('T'); sb.Append(arity.ToString());
}return sb.ToString();
}}
Roslyn Performance Lessons 3public class Example{
// Constructs a name like "Foo<T1, T2, T3>"public string GenerateFullTypeName(string name, int arity){
StringBuilder sb = new AcquireBuilder();sb.Append(name);if (arity != 0){
sb.Append("<");for (int i = 1; i < arity; i++){
sb.Append('T'); sb.Append(i.ToString());}sb.Append('T'); sb.Append(arity.ToString());
}return GetStringAndReleaseBuilder(sb);
}} OBJECT POOLING
Roslyn Performance Lessons 3[ThreadStatic]private static StringBuilder cachedStringBuilder;
private static StringBuilder AcquireBuilder(){
StringBuilder result = cachedStringBuilder;if (result == null){
return new StringBuilder();}result.Clear();cachedStringBuilder = null;return result;
}
private static string GetStringAndReleaseBuilder(StringBuilder sb){
string result = sb.ToString();cachedStringBuilder = sb;return result;
}