performance is a feature! - developer south coast - part 2
TRANSCRIPT
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.”
static void Profile(int iterations, Action action) {
action(); // warm up GC.Collect(); // clean up
var watch = new Stopwatch(); watch.Start(); for (int i = 0; i < iterations; i++) { action(); } watch.Stop();
Console.WriteLine("Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}
http://stackoverflow.com/questions/1047218/benchmarking-small-code-samples-in-c-can-this-implementation-be-improved
private static T Result;static void Profile<T>(int iterations, Func<T> func) {
func(); // warm up GC.Collect(); // clean up
var watch = new Stopwatch(); watch.Start(); for (int i = 0; i < iterations; i++) { Result = func(); } watch.Stop();
Console.WriteLine("Time Elapsed {0} ms", watch.ElapsedMilliseconds);
}
How?
Garbage Collection (GC)
Allocations are cheap, but cleaning up isn’t
Difficult to measure the impact of GC
http://www.slideshare.net/benemmett/net-memory-management-ndc-london https://vimeo.com/113632451
Stack Overflow Performance Lessons
Use static classes
Don’t be afraid to write your own toolsDapper, Jil, MiniProfiler,
Intimately know your platform - CLR
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, size); Logger.WriteLine(s); }}
Essential Truths Everyone Should Know about Performance in a Large Managed Codebase
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
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
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;}