-
1.
Performance is a Feature!
-
2.
Performance is a Feature!
Matt Warren
ca.com/apm
mattwarren.github.io
@matthewwarren
-
3.
Front-end
Database & Caching
CLR/JVM
Mechanical
Sympathy
-
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?
http://engineroom.ft.com/2016/04/04/a-faster-ft-com/
-
7.
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
-
8.
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
-
9.
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
-
10.
Never give up your
performance accidentally
Rico Mariani,
Performance Architect @
Microsoft
-
11.
What?
Averages
are bad
-
12.
"most people have
more than the average
number of legs"
- Hans Rosling
-
13.
https://blogs.msdn.microsoft.com/bharry/2016/03/28/introducing-application-analytics/
Application Insights Analytics
-
14.
When?
In production
You won't see ANY perf issues
during unit tests
You won't see ALL perf issues
in Development
-
15.
How?
Measure, measure, measure
1. Identify bottlenecks
2. Verify the optimisation works
-
16.
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.”
-
17.
How?
https://github.com/opserver/Opserver
-
18.
How?
https://github.com/opserver/Opserver
-
19.
How?
Micro-benchmarks
-
20.
How?
Profiling -> Micro-benchmarks
-
21.
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>();
}
http://github.com/PerfDotNet/BenchmarkDotNet
-
22.
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)
-
23.
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.
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 |
-
25.
How?
Garbage Collection (GC)
Allocations are cheap, but cleaning up isn’t
Difficult to measure the impact of GC
-
26.
https://samsaffron.com/archive/2011/10/28/in-managed-code-we-trust-our-
recent-battles-with-the-net-garbage-collector
-
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 Example
{
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 Example
{
public void Log(int id, int size)
{
var s = string.Format("{0}:{1}",
id.ToString(), size.ToString());
Logger.WriteLine(s);
}
}
AVOID BOXING
Know what’s going on under the hood
-
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
High level abstractions have a cost
-
32.
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
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 |
-
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
-
35.
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;
}
Reduce unnecessarily allocations
-
36.
Questions?
@matthewwarren
mattwarren.github.io
Which technology ; CLR, JVM, Go, Javascript
Type of Dev: Web, Mobile, Embedded
All of what I say applies to GC languages, i.e. CLR, JVM & Go
Henry Petroski (February 6, 1942) is an American engineer specializing in failure analysis. A professor both of civil engineering and history at Duke University, he is also a prolific author. Petroski has written over a dozen books – beginning with To Engineer is Human: The Role of Failure in Successful Design
Hans Rosling (born 27 July 1948)[1] is a Swedish medical doctor, academic, statistician, and public speaker. He is the Professor of International Health at Karolinska Institutet[2] and co-founder and chairman of the Gapminder Foundation, which developed the Trendalyzer software system.
Most famous for his energetic TED talks, explaining rate of development in the 3rd world