performance is a feature! - london .net user group
TRANSCRIPT
![Page 1: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/1.jpg)
Performance is a Feature!
![Page 2: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/2.jpg)
Performance is a Feature!
Matt Warrenca.com/apm
mattwarren.github.io@matthewwarren
![Page 3: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/3.jpg)
![Page 4: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/4.jpg)
Front-end
Database & Caching
.NET CLR
Mechanical Sympathy
![Page 5: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/5.jpg)
Why does performance matter?
What do we need to measure?
How we can fix the issues?
![Page 6: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/6.jpg)
Why?Save moneySave powerBad perf == brokenLost customers
Half a second delay caused a 20% drop in traffic (Google)
![Page 7: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/7.jpg)
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 Peteroski
![Page 8: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/8.jpg)
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
![Page 9: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/9.jpg)
Never give up your performance accidentally
Rico Mariani, Performance Architect @ Microsoft
![Page 10: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/10.jpg)
What?
Averages are bad
![Page 11: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/11.jpg)
![Page 12: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/12.jpg)
"most people have more than the average number of legs"
- Hans Rosling
![Page 13: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/13.jpg)
![Page 14: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/14.jpg)
![Page 15: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/15.jpg)
https://blogs.msdn.microsoft.com/bharry/2016/03/28/introducing-application-analytics/
Application Insights Analytics
![Page 16: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/16.jpg)
When?
In production
You won't see ANY perf issues during unit tests
You won't see ALL perf issues in Development
![Page 17: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/17.jpg)
How?
Measure, measure, measure
1. Identify bottlenecks2. Verify the optimisation works
![Page 18: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/18.jpg)
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.”
![Page 19: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/19.jpg)
How?
https://github.com/opserver/Opserver
![Page 20: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/20.jpg)
How?
https://github.com/opserver/Opserver
![Page 21: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/21.jpg)
How?
Micro-benchmarks
![Page 22: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/22.jpg)
How?
Profiling -> Micro-benchmarks
![Page 23: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/23.jpg)
![Page 24: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/24.jpg)
http://www.hanselman.com/blog/BenchmarkingNETCode.aspx
![Page 25: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/25.jpg)
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>();}
![Page 26: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/26.jpg)
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)
![Page 27: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/27.jpg)
BenchmarkDotNetBenchmarkDotNet=v0.9.4.0OS=Microsoft Windows NT 6.1.7601 Service Pack 1Processor=Intel(R) Core(TM) i7-4800MQ CPU @ 2.70GHz, ProcessorCount=8HostCLR=MS.NET 4.0.30319.42000, Arch=32-bit RELEASEJitModules=clrjit-v4.6.100.0
Type=Program Mode=Throughput
Method | Median | StdDev | Scaled |--------------------- |------------ |----------- |------- | RegularPropertyCall | Reflection |
![Page 28: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/28.jpg)
BenchmarkDotNetBenchmarkDotNet=v0.9.4.0OS=Microsoft Windows NT 6.1.7601 Service Pack 1Processor=Intel(R) Core(TM) i7-4800MQ CPU @ 2.70GHz, ProcessorCount=8HostCLR=MS.NET 4.0.30319.42000, Arch=32-bit RELEASEJitModules=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 |
![Page 29: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/29.jpg)
[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();}
![Page 30: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/30.jpg)
![Page 31: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/31.jpg)
![Page 32: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/32.jpg)
How?
Garbage Collection (GC)
Allocations are cheap, but cleaning up isn’t
Difficult to measure the impact of GC
![Page 33: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/33.jpg)
![Page 34: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/34.jpg)
![Page 35: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/35.jpg)
https://samsaffron.com/archive/2011/10/28/in-managed-code-we-trust-our-recent-battles-with-the-net-garbage-collector
![Page 36: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/36.jpg)
Stack Overflow Performance Lessons
Use static classes
Don’t be afraid to write your own toolsDapper, Jil, MiniProfiler,
Intimately know your platform - CLR
![Page 37: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/37.jpg)
Roslyn Performance Lessons 1public 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
![Page 38: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/38.jpg)
Roslyn Performance Lessons 1public 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); }} AVOID BOXING
![Page 39: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/39.jpg)
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); }}
![Page 40: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/40.jpg)
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
![Page 41: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/41.jpg)
BenchmarkDotNetBenchmarkDotNet=v0.9.4.0OS=Microsoft Windows NT 6.1.7601 Service Pack 1Processor=Intel(R) Core(TM) i7-4800MQ CPU @ 2.70GHz, ProcessorCount=8Frequency=2630654 ticks, Resolution=380.1336 ns, Timer=TSCHostCLR=MS.NET 4.0.30319.42000, Arch=32-bit RELEASEJitModules=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 |
![Page 42: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/42.jpg)
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(); }}
![Page 43: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/43.jpg)
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
![Page 44: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/44.jpg)
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;}
![Page 45: Performance is a feature! - London .NET User Group](https://reader035.vdocuments.us/reader035/viewer/2022070515/587a607b1a28ab520b8b772f/html5/thumbnails/45.jpg)
Questions?
@matthewwarren mattwarren.github.io
https://confocal.io/ Code: matt