SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
Performance is a feature! - London .NET User Group
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!
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!
4.
Why does performance matter?
What do we need to measure?
How we can fix the issues?
5.
Why?
Save money
Save power
Bad perf == broken
Lost customers
Half a second delay caused
a 20% drop in traffic
(Google)
6.
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
7.
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
8.
Never give up your
performance accidentally
Rico Mariani,
Performance Architect @
Microsoft
12.
When?
In production
You won't see ANY perf issues
during unit tests
You won't see ALL perf issues
in Development
13.
How?
Measure, measure, measure
1. Identify bottlenecks
2. Verify the optimisation works
14.
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.”
20.
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>();
}
21.
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)
22.
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 |
24.
[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();
}
25.
How?
Garbage Collection (GC)
Allocations are cheap, but cleaning up isn’t
Difficult to measure the impact of GC
27.
Stack Overflow Performance Lessons
Use static classes
Don’t be afraid to write your own tools
Dapper, Jil, MiniProfiler,
Intimately know your platform - CLR
28.
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
29.
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
30.
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);
}
}
31.
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
33.
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();
}
}
34.
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