Starting with the premise that "Performance is a Feature", this session will look at how to measure, what to measure and how get the best performance from your .NET code.
We will look at real-world examples from the Roslyn code-base and StackOverflow (the product), including how the .NET Garbage Collector needs to be tamed!
5. 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.”
13. 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
18. Stack Overflow Performance Lessons
Use static classes
Don’t be afraid to write your own tools
Dapper, Jil, MiniProfiler,
Intimately know your platform - CLR
19.
20. 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, size);
Logger.WriteLine(s);
}
}
Essential Truths Everyone Should Know about Performance in a Large Managed Codebase
21. 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);
}
}
AVOID BOXING
22. Roslyn Performance Lessons 2
class 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);
}
}
23. Roslyn Performance Lessons 2
class 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
24. Roslyn Performance Lessons 3
public 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();
}
}
25. Roslyn Performance Lessons 3
public 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
Who has: - any perf requirements - perf requirements with numbers! - any perf tests - perf test that are run continuously
Front-end
- YSlow, Google PageSpeed, CDN & caching
- "High Performance Web Sites" by Steve Sounder
Database & caching
- Learn to use SQL Profiler
- Redis or similar
- MiniProfiler
.NET (server-side) <- This is what we are looking at
Mechanical Sympathy
- Anything by Martin Thompson
- Disruptor and Disruptor.NET
- CPU caches (L1, L2, etc)
- memory access patterns
You’ll probably guess wrong!!
Consider adding performance unit tests,
Noda-Time does this, can graph performance over time, see if it’s regressed!!
MiniProfiler
Turn this on in Development and if possible in Production
Glimpse is an alternative
Runs on .NET,
Puts everything in 1 place, Web Server & Database
Summary metrics up front
Can drill-down into detailed metrics, including executed SQL, page load times, etc
Make sure you are really measuring what you think you are measuring!!
Warm up – For the JITter
Get GC out of the way
Lots of iterations
Use Stopwatch, NOT DateTime.Now
Have to be weary of the JITter
JITter will remove functions call if the return value isn’t used (sometimes)
Still not perfect, loop overhead can dominate!!! So unr
POSSIBLE DEMO (if time)
Make sure you are really measuring what you think you are measuring!!
Make sure you are really measuring what you think you are measuring!!
Both StackOverflow and Roslyn affected by this!!!!!
In the .NET Framework 4.5, there is background server garbage collection (before .NET 4.5 was Workstation only)
So until .NET 4.5, Server GC was STOP-THE-WORLD
In .NET 4.6 there is now TryStartNoGCRegion and EndNoGCRegion
Process Explorer
From Sysinternals
PerfView is a stand-alone utility, to help you debug CPU and memory problems
Light-weight and non-intrusive, can be used to on production apps with minimal impact
Uses ETW (Event Tracing for Windows), designed to be v. fast!!!!
Just and intro
Don’t need to say anything else here!
They were able to graph these results & equate them to Garbage Collector pauses!!!
They had good logging and measurements in place,
Ask "Any questions so far?”
At this point should be ~45 minutes in
Not long left!!!
They measured and found that all of these were on the HOT PATH