SlideShare a Scribd company logo
1 of 132
DAILY
PERFORMANCE
PITFALLS
ŁUKASZ PYRZYK
ŁUKASZ PYRZYK
• Co-founder of Dotnetos
• Senior Full Stack Cloud Developer at Sonova/JCommerce
• Tweets as @lukaszpyrzyk
AGENDA
• Assuming performance improvement by looking at code which may look faster
• Decompiling our code with Sharplab.io to understand how optimizer can predict our
ideas
• Story of the releasing product in debug mode
• Relying on the debug code behaviours and object state
• Surprising behaviours of tiered compilation
• Optimizing code with ArrayPool and ETW events
• Simple, but valuable optimization of the CosmosDB which come from official
documentations
• Steaming network data with ASP.NET
• Pitfalls of optimizing code without taking a wider perspective on the problem
ISSUE #1
ASSUMING PERFORMANCE
IMPROVEMENT
@lukaszpyrzyk
public void XOR(ref int x, ref int y)
{
x = x ^ y;
y = x ^ y;
x = x ^ y;
}
- No temp int variable
- int is 4 bytes, so it saves 4 bytes
- Assembly has XOR operation, so it’s 1:1, so it’s
fast
@lukaszpyrzyk
00007ffc`d7459170 XOR(Int32 ByRef, Int32 ByRef)
IL_0000: ldarg.1, IL_0001: ldarg.1
IL_0002: ldind.i4, IL_0003: ldarg.2
IL_0004: ldind.i4,
IL_0005: xor
IL_0006: stind.i4
00007ffc`d7459170 418b00 mov eax,dword ptr [r8]
00007ffc`d7459173 3102 xor dword ptr [rdx],eax
IL_0007: ldarg.2, IL_0008: ldarg.1
IL_0009: ldind.i4, IL_000a: ldarg.2
IL_000b: ldind.i4
IL_000c: xor
IL_000d: stind.i4
00007ffc`d7459175 8b02 mov eax,dword ptr [rdx]
00007ffc`d7459177 413100 xor dword ptr [r8],eax
IL_000e: ldarg.1, IL_000f: ldarg.1
IL_0010: ldind.i4, IL_0011: ldarg.2
IL_0012: ldind.i4
IL_0013: xor
IL_0014: stind.i4
00007ffc`d745917a 418b00 mov eax,dword ptr [r8]
00007ffc`d745917d 3102 xor dword ptr [rdx],eax
IL_0015: ret
00007ffc`d745917f c3 ret
00007ffc`d7459170 TempVariable(Int32 ByRef, Int32 ByRef)
IL_0000: ldarg.1
IL_0001: ldind.i4
IL_0002: stloc.0
00007ffc`d7459170 8b02 mov eax,dword ptr [rdx]
IL_0003: ldarg.1
IL_0004: ldarg.2
IL_0005: ldind.i4
IL_0006: stind.i4
00007ffc`d7459172 418b08 mov ecx,dword ptr [r8]
00007ffc`d7459175 890a mov dword ptr [rdx],ecx
IL_0007: ldarg.2
IL_0008: ldloc.0
IL_0009: stind.i4
00007ffc`d7459177 418900 mov dword ptr [r8],eax
IL_000a: ret
00007ffc`d745917a c3 ret
00007ff9`b7092140 418b00 mov eax,dword ptr [r8]
00007ff9`b7092143 3102 xor dword ptr [rdx],eax
00007ff9`b7092145 8b02 mov eax,dword ptr
[rdx]
00007ff9`b7092147 413100 xor dword ptr [r8],eax
00007ff9`b709214a 418b00 mov eax,dword ptr [r8]
00007ff9`b709214d 3102 xor dword ptr [rdx],eax
00007ff9`b709214f c3 ret
XOR
00007ff9`b70b2140 8b02 mov eax,dword ptr
[rdx]
00007ff9`b70b2142 418b08 mov ecx,dword ptr [r8]
00007ff9`b70b2145 890a mov dword ptr
[rdx],ecx
00007ff9`b70b2147 418900 mov dword ptr [r8],eax
00007ff9`b70b214a c3 ret
TempVariable
@lukaszpyrzyk
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.16299.1146
(1709/FallCreatorsUpdate/Redstone3)
Intel Core i5-7200U CPU 2.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores
Frequency=2648437 Hz, Resolution=377.5812 ns, Timer=TSC
Method Mean Error StdDev Median
XOR 2.8275 ns 0.0615 ns 0.0575 ns 2.8419 ns
@lukaszpyrzyk
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.16299.1146
(1709/FallCreatorsUpdate/Redstone3)
Intel Core i5-7200U CPU 2.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores
Frequency=2648437 Hz, Resolution=377.5812 ns, Timer=TSC
Method Mean Error StdDev Median
XOR 2.8275 ns 0.0615 ns 0.0575 ns 2.8419 ns
TempVariabl
e
0.0114 ns 0.0131 ns 0.0123 ns 0.0000 ns
@lukaszpyrzyk
The method duration is
indistinguishable from the empty
method duration
Requires Benchmarkdotnet v0.11.2+
public void AddAndSubtract(ref int x, ref int y)
{
x = x + y;
y = x - y;
x = x - y;
}
@lukaszpyrzyk
Method Mean Error StdDev Median
XOR 2.8275 ns 0.0615 ns 0.0575 ns 2.8419 ns
TempVariabl
e
0.0114 ns 0.0131 ns 0.0123 ns 0.0000 ns
AddAndSubtrac
t
2.8454 ns 0.0691 ns 0.0646 ns 2.8798 ns
@lukaszpyrzyk
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.16299.1146
(1709/FallCreatorsUpdate/Redstone3)
Intel Core i5-7200U CPU 2.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores
Frequency=2648437 Hz, Resolution=377.5812 ns, Timer=TSC
Method Runtime Mean Error StdDev Median
TempVariable Clr 0.0022 ns 0.0067 ns 0.0062 ns 0.0000 ns
AddAndSubtract Clr 3.0518 ns 0.0767 ns 0.0641 ns 3.0383 ns
XOR Clr 2.9713 ns 0.0636 ns 0.0594 ns 2.9579 ns
TempVariable Core 0.0199 ns 0.0264 ns 0.0418 ns 0.0000 ns
AddAndSubtract Core 3.0355 ns 0.0953 ns 0.1135 ns 3.0258 ns
XOR Core 2.8102 ns 0.0778 ns 0.0728 ns 2.7733 ns
TempVariable Mono 0.4762 ns 0.0937 ns 0.2704 ns 0.3619 ns
AddAndSubtract Mono 2.9212 ns 0.1042 ns 0.1115 ns 2.8869 ns
XOR Mono 2.8912 ns 0.0686 ns 0.0573 ns 2.8840 ns
@lukaszpyrzyk
public void M()
{
int x = 4096, y = 8192;
x = x ^ y;
y = x ^ y;
x = x ^ y;
Console.WriteLine(x);
Console.WriteLine(y);
}
@lukaszpyrzyk
public void M()
{
int x = 4096, y = 8192;
int temp = x;
x = y;
y = temp;
Console.WriteLine(x);
Console.WriteLine(y);
}
@lukaszpyrzyk
@lukaszpyrzyk
BENCHMARKING….
IT IS THE SAME!
@lukaszpyrzyk
Debug
assembly
30 lines
Release
assembly
8 lines
ISSUE #2
RELEASING PRODUCT IN
DEBUG MODE
@lukaszpyrzyk
@lukaszpyrzyk
YAML
@lukaszpyrzyk
YAMLDOTNET
PREVIOUS YAMLDOTNET BENCHMARKS
foreach(var test in tests)
{
Console.Write("{0}t{1}t", adapterName, test.GetType().Name);
var graph = test.Graph;
RunTest(serializer, graph); // warmup
if (!Stopwatch.IsHighResolution)
Console.Error.WriteLine("Stopwatch is not high resolution!");
var timer = Stopwatch.StartNew();
for (var i = 0; i < iterations; ++i)
RunTest(serializer, graph);
var duration = timer.Elapsed;
Console.WriteLine("{0}", duration.TotalMilliseconds / iterations);
}
ATTEMP WITH BENCHMARKDOTNET
[MemoryDiagnoser]
public class ReceiptTest
{
private readonly Receipt _receipt = new Receipt();
private readonly StringWriter _buffer = new StringWriter();
private readonly ISerializer _serializer = new SerializerBuilder()
.WithNamingConvention(new CamelCaseNamingConvention())
.Build();
[Benchmark]
public void Serialize()
{
_serializer.Serialize(_buffer, _receipt.Graph);
}
}
dotnet run –c Release
// Validating benchmarks:
Assembly YamlDotNet.PerformanceTests.vlatest which defines benchmarks
references non-optimized YamlDotNet
- If you own this dependency, please, build it in RELEASE.
- If you don't, you can create custom config with DontFailOnError to
disable our custom policy and allow this benchmark to run.
PROBLEM
New csproj format doesn’t have the same
behaviour as the old one. Configurations like
Release-* don’t inherit from Release
configuration.
FIX
<PropertyGroup Condition=" '$(Configuration)' == 'Release-Signed' Or
'$(Configuration)' == 'Release-Unsigned' ">
<DefineConstants>$(DefineConstants);RELEASE;TRACE</DefineConstants>
<DebugSymbols>false</DebugSymbols>
<DebugType>portable</DebugType>
<Optimize>true</Optimize>
</PropertyGroup>
FIX
-----------------------------------------------------------------------------------
| | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
-----------------------------------------------------------------------------------
| v1.2.1 | 128.7 us | 1.285 us | 1.202 us | 5.8594 | 0.2441 | 23.66 KB |
| v2.2.0 | 240.6 us | 3.467 us | 3.243 us | 18.0664 | 0.4883 | 60.03 KB |
| v2.3.0 | 307.9 us | 6.112 us | 10.21 us | 20.0195 | 0.4883 | 67.32 KB |
| v3.8.0 | 292.2 us | 4.225 us | 3.952 us | 21.4844 | 0.4883 | 70.82 KB |
| v4.0.0 | 283.2 us | 3.075 us | 2.876 us | 22.9492 | 0.4883 | 74.26 KB |
| v5.2.1 | 539.5 us | 5.710 us | 5.062 us | 8.7891 | 0.9766 | 30.82 KB |
| vlatest | 145.8 us | 1.671 us | 1.563 us | 8.3008 | 0.4883 | 30.7 KB |
----------------------------------------------------------------------------------
@lukaszpyrzyk
ISSUE #3
BUFFERING
RESPONSES
@lukaszpyrzyk
@lukaszpyrzyk
BUFFERING A FILE
Github
blob
User
https://github.com/dotnet/corefx/archive/v2.2.0-preview3.zi
@lukaszpyrzyk
BUFFERING A FILE
Github
blob
Server User
http://dotnet.microsoft.com/download/
@lukaszpyrzyk
BUFFERING A FILE
public async Task<IActionResult> WithBuffering()
{
var request = new HttpRequestMessage(HttpMethod.Get,
"dotnet/corefx/archive/v2.2.0-preview3.zip");
var response = await _client.Client.SendAsync(request);
var stream = await response.Content.ReadAsStreamAsync();
var contentType = response.Content.Headers.ContentType.MediaType;
return new FileStreamResult(stream, contentType);
}
@lukaszpyrzyk
@lukaszpyrzyk
BUFFERING A FILE
public async Task<IActionResult> WithoutBuffering()
{
var request = new HttpRequestMessage(HttpMethod.Get,
"dotnet/corefx/archive/v2.2.0-preview3.zip");
var response = await _client.Client.SendAsync(request,
HttpCompletionOption.ResponseHeadersRead);
var stream = await response.Content.ReadAsStreamAsync();
var contentType = response.Content.Headers.ContentType.MediaType;
return new FileStreamResult(stream, contentType);
}
@lukaszpyrzyk
@lukaszpyrzyk
BUFFERING A FILE
public async Task<Stream> Stream()
{
var request = new HttpRequestMessage(HttpMethod.Get,
"dotnet/corefx/archive/v2.2.0-preview3.zip");
var response = await
_client.Client.GetStreamAsync(request.RequestUri);
return response;
}
ISSUE #4
RELYING ON THE OBJECT STATE
static void Main(string[] args)
{
var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100);
Console.WriteLine("Timer started?");
GC.Collect();
Console.Read();
}
CODE
dotnet run -c Debug
14/10/2019 18:43:22
Timer started?
14/10/2019 18:43:22
14/10/2019 18:43:22
14/10/2019 18:43:22
[…]
DEBUG
dotnet run -c Release
Timer started?
14/10/2019 18:48:56
RELEASE
EAGER ROOT COLLECTION
IT IS A JUST-IN-TIME COMPILER
OPTIMIZATION WHICH MAKES LOCAL
REFERENCES IRRELEVANT AFTER THEIR
LAST USAGE
KEEP ALIVE
static void Main(string[] args)
{
var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100);
Console.WriteLine("Timer started?");
GC.Collect();
Console.Read();
GC.KeepAlive(timer);
}
CALLING DISPOSE
static void Main(string[] args)
{
var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100);
Console.WriteLine("Timer started?");
GC.Collect();
Console.Read();
timer.Dispose();
}
CALLING DISPOSE
static void Main(string[] args)
{
using (var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100))
{
Console.WriteLine("Timer started?");
GC.Collect();
Console.Read();
}
}
CALLING DISPOSE
C# 8.0
CALLING DISPOSE
static void Main(string[] args)
{
using var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0,
100);
Console.WriteLine("Timer started?");
GC.Collect();
Console.Read();
}
CALLING DISPOSE
[NullableContext(1)]
[Nullable(0)]
public sealed class Timer : MarshalByRefObject, IAsyncDisposable, Idisposable
{
/// <summary>Releases all resources used by the current instance of <see
cref="T:System.Threading.Timer" />.</summary>
/// <returns>A <see cref="T:System.Threading.Tasks.ValueTask" /> that completes
when all work associated with the timer has ceased.</returns>
public ValueTask DisposeAsync();
}
CALLING DISPOSE
static async Task Main(string[] args)
{
await using var timer =
new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100);
Console.WriteLine("Timer started?");
GC.Collect();
Console.Read();
}
static void Main(string[] args)
{
var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100);
Console.WriteLine("Timer started?");
GC.Collect();
Console.Read();
}
CODE
dotnet run -c Release
Timer started?
16/10/2019 16:36:51
16/10/2019 16:36:51
16/10/2019 16:36:51
16/10/2019 16:36:51
16/10/2019 16:36:51
16/10/2019 16:36:51
16/10/2019 16:36:51
[..]
RELEASE
WHAT?
ISSUE #4
FORGETTING ABOUT
TIERED COMPILATION
.NET Core version Tiered compilation
2.0 None
2.1 Optional
3.0 Default
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TieredCompilation>true</TieredCompilation>
</PropertyGroup>
</Project>
RELEASE
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
RELEASE
TIERED COMPILATION
CAN INFLUENCE THE PROFILING AND
BENCHMARKING RESULTS.
IT CAN CHANGE RESULTS OF SAMPLES
FROM BOOKS OR BLOG POSTS
@lukaszpyrzyk
ISSUE #5
NOT USING ETW EVENTS
private static async Task Default()
{
var buffer = new byte[8 * 1024];
for (int i = 0; i < Iterations; i++)
{
foreach (var file in Directory.EnumerateFiles("images"))
{
var fileInfo = new FileInfo(file);
var array = new byte[fileInfo.Length];
await using var stream = File.OpenRead(file);
await ReadStreamToArray(fileInfo, stream, buffer, array);
}
}
}
CommandLine:
"C:devDPFSrcDPF.ArrayPoolbinReleasenetcoreapp3.0DPF.Arra
yPool.exe"
Runtime Version: V 4.0.30319.0 (built on 13/09/2019 01:02:04)
CLR Startup Flags: None
Total CPU Time: 11,368 msec
Total GC CPU Time: 19 msec
Total Allocs : 1,263.242 MB
GC CPU MSec/MB Alloc : 0.015 MSec/MB
Total GC Pause: 20.5 msec
% Time paused for Garbage Collection: 0.3%
% CPU Time spent Garbage Collecting: 0.2%
Max GC Heap Size: 145.235 MB
Peak Process Working Set: 170.570 MB
Peak Virtual Memory Usage: 2,199,714.988 MB
ARRAYPOOL<BYTE>.SHARED
var arrayPool = ArrayPool<byte>.Shared; var buffer = arrayPool.Rent(8 * 1024);
try
{
for (int i = 0; i < Iterations; i++)
{
foreach (var file in Directory.EnumerateFiles("images"))
{
var fileInfo = new FileInfo(file);
var array = arrayPool.Rent(Convert.ToInt32(fileInfo.Length));
try
{
await using var stream = File.OpenRead(file);
await ReadStreamToArray(fileInfo, stream, buffer, array);
}
finally
{
arrayPool.Return(array);
}
}
}
}
finally
{
arrayPool.Return(buffer);
}
CommandLine:
"C:devDPFSrcDPF.ArrayPoolbinReleasenetcoreapp3.0DPF.Arra
yPool.exe"
Runtime Version: V 4.0.30319.0 (built on 13/09/2019 01:02:04)
CLR Startup Flags: None
Total CPU Time: 12,527 msec
Total GC CPU Time: 12 msec
Total Allocs : 1,014.148 MB
GC CPU MSec/MB Alloc : 0.012 MSec/MB
Total GC Pause: 25.1 msec
% Time paused for Garbage Collection: 0.3%
% CPU Time spent Garbage Collecting: 0.1%
Max GC Heap Size: 146.111 MB
Peak Process Working Set: 158.175 MB
Peak Virtual Memory Usage: 2,199,715.676 MB
Remarks
Using the ArrayPool<T> class to rent and return
buffers (using the Rent and Return methods)
improve performance in situations where arrays
are created and destroyed frequently, resulting
significant memory pressure on the garbage
collector.
ARRAYPOOL<BYTE>.CREATE
var biggestFile = Directory.GetFiles("images").Select(x => new FileInfo(x)).Select(x =>
x.Length).Max();
var arrayPool = ArrayPool<byte>.Create(maxArrayLength: Convert.ToInt32(biggestFile),
maxArraysPerBucket: 1);
var buffer = arrayPool.Rent(8 * 1024);
try
{
for (int i = 0; i < Iterations; i++)
{
foreach (var file in Directory.EnumerateFiles("images"))
{
var fileInfo = new FileInfo(file);
var array = arrayPool.Rent(Convert.ToInt32(fileInfo.Length));
try
{
await using var stream = File.OpenRead(file);
await ReadStreamToArray(fileInfo, stream, buffer, array);
}
finally
{
arrayPool.Return(array);
}
}
}
}
finally
{
arrayPool.Return(buffer);
}
CommandLine:
"C:devDPFSrcDPF.ArrayPoolbinReleasenetcoreapp3.0DPF.Arra
yPool.exe"
Runtime Version: V 4.0.30319.0 (built on 13/09/2019 01:02:04)
CLR Startup Flags: None
Total CPU Time: 11,358 msec
Total GC CPU Time: 8 msec
Total Allocs : 58.261 MB
GC CPU MSec/MB Alloc : 0.137 MSec/MB
Total GC Pause: 11.3 msec
% Time paused for Garbage Collection: 0.2%
% CPU Time spent Garbage Collecting: 0.1%
Max GC Heap Size: 37.899 MB
Peak Process Working Set: 51.962 MB
Peak Virtual Memory Usage: 2,199,574.643 MB
Allocated bytes Max GC Heap Size
New arrays 1,263.242 MB 145.235 MB
Shared ArrayPool 1,014.148 MB 146.111 MB
Custom ArrayPool<byte> 58.261 MB 37.899 MB
TIP
ARRAYPOOL.SHARED ALLOCATES
MEMORY IF IT NEEDS TO RENT ARRAY
BIGGER THAN 2^20 BYTES (1MB)
@lukaszpyrzyk
ISSUE #6
RELYING ON THE LIBRARY AND CROSS
PLATFORM FEATURES
@lukaszpyrzyk
public class TelemetryEntry
{
public DateTimeOffset Timestamp { get; set; }
public int UserId { get; set; }
}
@lukaszpyrzyk
[Route("[controller]")]
[ApiController]
public class TelemetryController : Controller
{
[HttpPut]
public async Task<IActionResult> Insert([FromServices]
DataStorageService db)
{
var entry = CreateEntry();
await db.Insert(entry);
return NoContent();
}
}
@lukaszpyrzyk
@lukaszpyrzyk
public class DataStorageService
{
private readonly DataStorageServiceOptions _options;
private readonly DocumentClient _client;
public SlowDataStorageService(DataStorageServiceOptions options)
{
_options = options;
_client = new DocumentClient(options.Endpoint, options.ApiKey);
_client.CreateDatabaseIfNotExistsAsync(new Database { Id =
options.DatabaseName }).GetAwaiter().GetResult();
_client.CreateDocumentCollectionIfNotExistsAsync(
UriFactory.CreateDatabaseUri(options.DatabaseName),
new DocumentCollection { Id = options.CollectionName })
.GetAwaiter().GetResult();
}
}
GetAwaiter().GetResult();
GetAwaiter().GetResult()
@lukaszpyrzyk
public async Task Insert(TelemetryEntry telemetryEntry)
{
var collectionUri =
UriFactory.CreateDocumentCollectionUri(_options.DatabaseName,
_options.CollectionName);
await _client.CreateDocumentAsync(collectionUri,
telemetryEntry);
}
@lukaszpyrzyk
public void ConfigureServices(IServiceCollection services)
{
var dbOptions = GetOptions();
services.AddSingleton(dbOptions);
services.AddTransient<DataStorageService>();
}
@lukaszpyrzyk
AddTransient
TESTING – NO DOCS
Running 30s test @
http://localhost:5000/telemetry/insert/slow
1 threads and 1 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 876.89ms 45.82ms 993.87ms 76.47%
Req/Sec 0.88 0.33 1.00 88.24%
34 requests in 30.07s, 2.69KB read
Requests/sec: 1.13
Transfer/sec: 91.57B
@lukaszpyrzyk
QUITE SLOW
QUITE UGLY
@lukaszpyrzyk
public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<Task<T>> valueFactory) :
base(valueFactory)
{
}
}
@lukaszpyrzyk
public class DataStorageService
{
private readonly AsyncLazy<DocumentClient> _clientFactory;
private readonly Uri _collectionUri;
public DataStorageService(DataStorageServiceOptions options)
{
_collectionUri =
UriFactory.CreateDocumentCollectionUri(options.DatabaseName,
options.CollectionName);
_clientFactory = new AsyncLazy<DocumentClient>(async () =>
{
var client = new DocumentClient(options.Endpoint,
options.ApiKey);
await InitialDatabase(client, options);
});
}
}
@lukaszpyrzyk
public async Task Insert(TelemetryEntry telemetryEntry)
{
var client = await _clientFactory.Value;
await client.CreateDocumentAsync(_collectionUri, telemetryEntry);
}
@lukaszpyrzyk
public void ConfigureServices(IServiceCollection services)
{
var dbOptions = GetOptions();
services.AddSingleton(dbOptions);
services.AddSingleton<DataStorageService>();
}
@lukaszpyrzyk
TESTING - OPTIMIZATIONS
@lukaszpyrzyk
0
2
4
6
8
10
12
No docs Cleaning & singleton
Requests per second
_clientFactory = new AsyncLazy<DocumentClient>(async () =>
{
var client = new DocumentClient(options.Endpoint,
options.ApiKey, new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp
});
await InitialDatabase(client, options);
});
@lukaszpyrzyk
TESTING – DIRECT / TCP
@lukaszpyrzyk
0
2
4
6
8
10
12
14
No docs Cleaning & singleton Direct / TCP
Requests per second
THE GONEEXCEPTION STORY
• Microservices
• CosmosDB
• Migration to the Direct/TCP connection policy, feature
toggle
• Thousands of the GoneException saying “The requested
resource is no longer available at the server”
• We have a bug!!!
• Race condition? Dispose? Network down? Firewall?
@lukaszpyrzyk
@lukaszpyrzyk
@lukaszpyrzyk
@lukaszpyrzyk
THE GONEEXCEPTION STORY
GoneException(“The requested resource is no longer available at the
server”)
might be
PlatformNotSupportedException();
@lukaszpyrzyk
https://github.com/Azure/azure-cosmosdb-dotnet/issues/194
@lukaszpyrzyk
ISSUE #7
LET’S OPTIMIZE IT
@lukaszpyrzyk
THE BUSINESS PROBLEM
• This is very important for our
company
• It’s PoC
• Please make it ASAP
• Performance doesn’t matter
• Don’t spend to much time on it
• Keep clean and easy to understand
for another developers
@lukaszpyrzyk
public ulong SecretAlgorithm(ulong n)
{
if (n == 1 || n == 2) return 1;
return SecretAlgorithm(n - 2) + SecretAlgorithm(n - 1);
}
@lukaszpyrzyk
public ulong Fibonacci(ulong n)
{
if (n == 1 || n == 2) return 1;
return Fibonacci(n - 2) + Fibonacci(n - 1);
}
@lukaszpyrzyk
THE BUSINESS PROBLEM
• It works
• It is simple
@lukaszpyrzyk
THE BUSINESS PROBLEM
Make it faster!
@lukaszpyrzyk
THE BUSINESS PROBLEM
What kind of
optimizations
techniques do I
know?
@lukaszpyrzyk
public ulong Fibonacci(ulong n)
{
if (n == 1 || n == 2) return 1;
var a = Task.Run(() => Fibonacci(n - 2));
var b = Task.Run(() => Fibonacci(n - 1));
Task.WaitAll(a, b);
return a.Result + b.Result;
}
@lukaszpyrzyk
@lukaszpyrzyk
3,130.90
230,628.90
0.00
50,000.00
100,000.00
150,000.00
200,000.00
250,000.00
300,000.00
Default Recursive TPL
n = 15, ns
47,396,067.95
4,621,743,140.75
0.00
1,000,000,000.00
2,000,000,000.00
3,000,000,000.00
4,000,000,000.00
5,000,000,000.00
6,000,000,000.00
Default Recursive TPL
n = 35, ns
public ulong Fibonacci(ulong n)
{
if (n == 1 || n == 2) return 1;
var a = Task.Run(() => FibonacciImplementation(n - 2));
var b = Task.Run(() => FibonacciImplementation(n - 1));
Task.WaitAll(a, b);
return a.Result + b.Result;
}
private ulong FibonacciImplementation(ulong n)
{
if (n == 1 || n == 2) return 1;
return Recursive(n - 2) + Recursive(n - 1);
}
@lukaszpyrzyk
@lukaszpyrzyk
3,130.90
6,055.02
0.00
1,000.00
2,000.00
3,000.00
4,000.00
5,000.00
6,000.00
7,000.00
Default Recursive TPL smarter
N = 15, ns
@lukaszpyrzyk
47,396,067.95
31,406,175.55
0.00
5,000,000.00
10,000,000.00
15,000,000.00
20,000,000.00
25,000,000.00
30,000,000.00
35,000,000.00
40,000,000.00
45,000,000.00
50,000,000.00
Default Recursive TPL smarter
N = 35, ns
LET’S THINK
@lukaszpyrzyk
public static ulong Recursive(ulong n)
{
Console.WriteLine($"Calculating Fibonacci for {n}");
if (n == 1 || n == 2) return 1;
return Recursive(n - 2) + Recursive(n - 1);
}
@lukaszpyrzyk
Fibonacci(5);
Calculating Fibonacci for 5
Calculating Fibonacci for 3
Calculating Fibonacci for 1
Calculating Fibonacci for 2
Calculating Fibonacci for 4
Calculating Fibonacci for 2
Calculating Fibonacci for 3
Calculating Fibonacci for 1
Calculating Fibonacci for 2
@lukaszpyrzyk
WE DO THE SAME JOB
SEVERAL TIMES
MEMOIZATION
It is an optimization technique used primarily to
speed up computer programs by storing the results
of expensive function calls and returning the
cached result when the same inputs occur again
@lukaszpyrzyk
MEMOIZATION
public ulong Fibonacci(ulong n)
{
if (n == 1 || n == 2) return 1;
var results = new ulong[n];
results[0] = 1;
results[1] = 1;
return FibWithMemoization(n, results);
}
@lukaszpyrzyk
MEMOIZATION
private static ulong FibWithMemoization(ulong n, ulong[] results)
{
var current = n - 1;
var previous = current - 1;
var beforePrevious = previous - 1;
if (results[beforePrevious] == 0)
results[beforePrevious] = FibWithMemoization(previous, results);
if (results[previous] == 0)
results[previous] = FibWithMemoization(current, results);
results[current] = results[beforePrevious] + results[previous];
return results[n - 1];
}
@lukaszpyrzyk
@lukaszpyrzyk
3,130.90
6,055.02
69.597
0.00
1,000.00
2,000.00
3,000.00
4,000.00
5,000.00
6,000.00
7,000.00
8,000.00
Default Recursive TPL smarter Memoization
N = 15, ns
@lukaszpyrzyk
47,396,067.95
31,406,175.55
181.442
0.00
10,000,000.00
20,000,000.00
30,000,000.00
40,000,000.00
50,000,000.00
60,000,000.00
Default Recursive TPL smarter Memoization
N = 35, ns
THE BUSINESS PROBLEM
WHAT WE MISSED?
@lukaszpyrzyk
public ulong Fibonacci(ulong n)
{
if (n == 1 || n == 2) return 1;
ulong a = 1, b = 1;
for (ulong i = 2; i < n; i++)
{
ulong temp = a + b;
a = b;
b = temp;
}
return b;
}
@lukaszpyrzyk
@lukaszpyrzyk
69.597
7.38
0
10
20
30
40
50
60
70
80
90
Memoization Iterative
N = 15, ns
@lukaszpyrzyk
181.442
17.33
0
50
100
150
200
250
Memoization Iterative
N = 35, ns
TIP
BEFORE DOING OPTIMIZATIONS
MAKE SURE THAT CURRENT
SOLUTION STILL FITS
@lukaszpyrzyk
SUMMARY
• We should always validate our performance improvements by measurement
• Releasing product in debug sounds funny, but there are real cases where by mistake
debug code was shipped to the clients
• Tiered compilation is new in .NET world and we need get used to it. It is a good idea to
disable tierec compilation for profiling and benchmarking or get code warm
• Reading documentation and API notes may give you easy performance boost, for
example by making CosmosDB client singleton with Direct connection or using
HttpCompletionOption
• ETW event are a great collection of knowledge about our application, for example
about ArrayPool usage
• Before doing code optimizations we should understand how it is used
LINKS
• Konrad Kokosa - Pro .NET Memory Management, https://prodotnetmemory.com/
• Andrey Akinshin - Pro .NET Benchmarking,
https://www.apress.com/gp/book/9781484249406
• https://github.com/lukasz-pyrzyk/DailyPerformancePitfalls
• https://docs.microsoft.com/en-us/azure/cosmos-db/performance-tips
• https://docs.microsoft.com/en-us/azure/cosmos-db/sql-api-sql-query-
metricshttp://www.tugberkugurlu.com/archive/efficiently-streaming-large-http-responses-
with-httpclient
• https://github.com/davidfowl/AspNetCoreDiagnosticScenarios
• https://wojciechnagorski.com/2018/12/how-i-improved-the-yamldotnet-performance-by-
370/
• https://github.com/aaubry/YamlDotNet/pull/356
@lukaszpyrzyk
10-11 October 2019
Warsaw - Poland
dotnetos.org
Thank you!
@lukaszpyrzyk
lukasz.pyrzyk@gmail.com

More Related Content

What's hot

Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...
Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...
Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...JAX London
 
Molecular Shape Searching on GPUs: A Brave New World
Molecular Shape Searching on GPUs: A Brave New WorldMolecular Shape Searching on GPUs: A Brave New World
Molecular Shape Searching on GPUs: A Brave New WorldCan Ozdoruk
 
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solverS4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solverPraveen Narayanan
 
The Weather of the Century Part 2: High Performance
The Weather of the Century Part 2: High PerformanceThe Weather of the Century Part 2: High Performance
The Weather of the Century Part 2: High PerformanceMongoDB
 
Optimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and Latency
Optimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and LatencyOptimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and Latency
Optimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and LatencyHenning Jacobs
 
Ceph Day New York 2014: Ceph, a physical perspective
Ceph Day New York 2014: Ceph, a physical perspective Ceph Day New York 2014: Ceph, a physical perspective
Ceph Day New York 2014: Ceph, a physical perspective Ceph Community
 
Understanding the Disruptor
Understanding the DisruptorUnderstanding the Disruptor
Understanding the DisruptorTrisha Gee
 
pstack, truss etc to understand deeper issues in Oracle database
pstack, truss etc to understand deeper issues in Oracle databasepstack, truss etc to understand deeper issues in Oracle database
pstack, truss etc to understand deeper issues in Oracle databaseRiyaj Shamsudeen
 
Cassandra Performance Benchmark
Cassandra Performance BenchmarkCassandra Performance Benchmark
Cassandra Performance BenchmarkBigstep
 
Memory, Big Data, NoSQL and Virtualization
Memory, Big Data, NoSQL and VirtualizationMemory, Big Data, NoSQL and Virtualization
Memory, Big Data, NoSQL and VirtualizationBigstep
 
OpenBSD/sgi SMP implementation for Origin 350
OpenBSD/sgi SMP implementation for Origin 350OpenBSD/sgi SMP implementation for Origin 350
OpenBSD/sgi SMP implementation for Origin 350Takuya ASADA
 
Profiling & Testing with Spark
Profiling & Testing with SparkProfiling & Testing with Spark
Profiling & Testing with SparkRoger Rafanell Mas
 
Engineering fast indexes (Deepdive)
Engineering fast indexes (Deepdive)Engineering fast indexes (Deepdive)
Engineering fast indexes (Deepdive)Daniel Lemire
 
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法MITSUNARI Shigeo
 
Weather of the Century: Design and Performance
Weather of the Century: Design and PerformanceWeather of the Century: Design and Performance
Weather of the Century: Design and PerformanceMongoDB
 
Concurrent data structures in javaslang circuitbreaker
Concurrent data structures in javaslang circuitbreakerConcurrent data structures in javaslang circuitbreaker
Concurrent data structures in javaslang circuitbreakerBogdan Storozhuk
 

What's hot (20)

Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...
Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...
Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...
 
Molecular Shape Searching on GPUs: A Brave New World
Molecular Shape Searching on GPUs: A Brave New WorldMolecular Shape Searching on GPUs: A Brave New World
Molecular Shape Searching on GPUs: A Brave New World
 
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solverS4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
 
The Weather of the Century Part 2: High Performance
The Weather of the Century Part 2: High PerformanceThe Weather of the Century Part 2: High Performance
The Weather of the Century Part 2: High Performance
 
200.1,2-Capacity Planning
200.1,2-Capacity Planning200.1,2-Capacity Planning
200.1,2-Capacity Planning
 
STANDARD CELL LIBRARY DESIGN
STANDARD CELL LIBRARY DESIGNSTANDARD CELL LIBRARY DESIGN
STANDARD CELL LIBRARY DESIGN
 
Lrz kurs: big data analysis
Lrz kurs: big data analysisLrz kurs: big data analysis
Lrz kurs: big data analysis
 
SOFA Tutorial
SOFA TutorialSOFA Tutorial
SOFA Tutorial
 
Optimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and Latency
Optimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and LatencyOptimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and Latency
Optimizing Kubernetes Resource Requests/Limits for Cost-Efficiency and Latency
 
Ceph Day New York 2014: Ceph, a physical perspective
Ceph Day New York 2014: Ceph, a physical perspective Ceph Day New York 2014: Ceph, a physical perspective
Ceph Day New York 2014: Ceph, a physical perspective
 
Understanding the Disruptor
Understanding the DisruptorUnderstanding the Disruptor
Understanding the Disruptor
 
pstack, truss etc to understand deeper issues in Oracle database
pstack, truss etc to understand deeper issues in Oracle databasepstack, truss etc to understand deeper issues in Oracle database
pstack, truss etc to understand deeper issues in Oracle database
 
Cassandra Performance Benchmark
Cassandra Performance BenchmarkCassandra Performance Benchmark
Cassandra Performance Benchmark
 
Memory, Big Data, NoSQL and Virtualization
Memory, Big Data, NoSQL and VirtualizationMemory, Big Data, NoSQL and Virtualization
Memory, Big Data, NoSQL and Virtualization
 
OpenBSD/sgi SMP implementation for Origin 350
OpenBSD/sgi SMP implementation for Origin 350OpenBSD/sgi SMP implementation for Origin 350
OpenBSD/sgi SMP implementation for Origin 350
 
Profiling & Testing with Spark
Profiling & Testing with SparkProfiling & Testing with Spark
Profiling & Testing with Spark
 
Engineering fast indexes (Deepdive)
Engineering fast indexes (Deepdive)Engineering fast indexes (Deepdive)
Engineering fast indexes (Deepdive)
 
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
 
Weather of the Century: Design and Performance
Weather of the Century: Design and PerformanceWeather of the Century: Design and Performance
Weather of the Century: Design and Performance
 
Concurrent data structures in javaslang circuitbreaker
Concurrent data structures in javaslang circuitbreakerConcurrent data structures in javaslang circuitbreaker
Concurrent data structures in javaslang circuitbreaker
 

Similar to .NET Fest 2019. Łukasz Pyrzyk. Daily Performance Fuckups

Klessydra t - designing vector coprocessors for multi-threaded edge-computing...
Klessydra t - designing vector coprocessors for multi-threaded edge-computing...Klessydra t - designing vector coprocessors for multi-threaded edge-computing...
Klessydra t - designing vector coprocessors for multi-threaded edge-computing...RISC-V International
 
Cncf k8s_network_part1
Cncf k8s_network_part1Cncf k8s_network_part1
Cncf k8s_network_part1Erhwen Kuo
 
GDC2014: Boosting your ARM mobile 3D rendering performance with Umbra
GDC2014: Boosting your ARM mobile 3D rendering performance with Umbra GDC2014: Boosting your ARM mobile 3D rendering performance with Umbra
GDC2014: Boosting your ARM mobile 3D rendering performance with Umbra Umbra Software
 
Understanding Performance with DTrace
Understanding Performance with DTraceUnderstanding Performance with DTrace
Understanding Performance with DTraceahl0003
 
Как понять, что происходит на сервере? / Александр Крижановский (NatSys Lab.,...
Как понять, что происходит на сервере? / Александр Крижановский (NatSys Lab.,...Как понять, что происходит на сервере? / Александр Крижановский (NatSys Lab.,...
Как понять, что происходит на сервере? / Александр Крижановский (NatSys Lab.,...Ontico
 
PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)
PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)
PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)Андрей Новиков
 
Ground to ns3 - Basic wireless topology implementation
Ground to ns3 - Basic wireless topology implementationGround to ns3 - Basic wireless topology implementation
Ground to ns3 - Basic wireless topology implementationJawad Khan
 
Debugging linux issues with eBPF
Debugging linux issues with eBPFDebugging linux issues with eBPF
Debugging linux issues with eBPFIvan Babrou
 
POLYTEDA PowerDRC/LVS overview
POLYTEDA PowerDRC/LVS overviewPOLYTEDA PowerDRC/LVS overview
POLYTEDA PowerDRC/LVS overviewAlexander Grudanov
 
Experiences in ELK with D3.js for Large Log Analysis and Visualization
Experiences in ELK with D3.js  for Large Log Analysis  and VisualizationExperiences in ELK with D3.js  for Large Log Analysis  and Visualization
Experiences in ELK with D3.js for Large Log Analysis and VisualizationSurasak Sanguanpong
 
Whose Stack Is It Anyway?
Whose Stack Is It Anyway?Whose Stack Is It Anyway?
Whose Stack Is It Anyway?Ian Thomas
 
Super scaling singleton inserts
Super scaling singleton insertsSuper scaling singleton inserts
Super scaling singleton insertsChris Adkin
 
Make ARM Shellcode Great Again
Make ARM Shellcode Great AgainMake ARM Shellcode Great Again
Make ARM Shellcode Great AgainSaumil Shah
 
Docker Logging and analysing with Elastic Stack - Jakub Hajek
Docker Logging and analysing with Elastic Stack - Jakub Hajek Docker Logging and analysing with Elastic Stack - Jakub Hajek
Docker Logging and analysing with Elastic Stack - Jakub Hajek PROIDEA
 
Docker Logging and analysing with Elastic Stack
Docker Logging and analysing with Elastic StackDocker Logging and analysing with Elastic Stack
Docker Logging and analysing with Elastic StackJakub Hajek
 
IxVM on CML
IxVM on CMLIxVM on CML
IxVM on CMLnpsg
 
MongoDB Days Silicon Valley: MongoDB and the Hadoop Connector
MongoDB Days Silicon Valley: MongoDB and the Hadoop ConnectorMongoDB Days Silicon Valley: MongoDB and the Hadoop Connector
MongoDB Days Silicon Valley: MongoDB and the Hadoop ConnectorMongoDB
 
Varnish @ Velocity Ignite
Varnish @ Velocity IgniteVarnish @ Velocity Ignite
Varnish @ Velocity IgniteArtur Bergman
 

Similar to .NET Fest 2019. Łukasz Pyrzyk. Daily Performance Fuckups (20)

RISC-V Zce Extension
RISC-V Zce ExtensionRISC-V Zce Extension
RISC-V Zce Extension
 
Brkdct 3101
Brkdct 3101Brkdct 3101
Brkdct 3101
 
Klessydra t - designing vector coprocessors for multi-threaded edge-computing...
Klessydra t - designing vector coprocessors for multi-threaded edge-computing...Klessydra t - designing vector coprocessors for multi-threaded edge-computing...
Klessydra t - designing vector coprocessors for multi-threaded edge-computing...
 
Cncf k8s_network_part1
Cncf k8s_network_part1Cncf k8s_network_part1
Cncf k8s_network_part1
 
GDC2014: Boosting your ARM mobile 3D rendering performance with Umbra
GDC2014: Boosting your ARM mobile 3D rendering performance with Umbra GDC2014: Boosting your ARM mobile 3D rendering performance with Umbra
GDC2014: Boosting your ARM mobile 3D rendering performance with Umbra
 
Understanding Performance with DTrace
Understanding Performance with DTraceUnderstanding Performance with DTrace
Understanding Performance with DTrace
 
Как понять, что происходит на сервере? / Александр Крижановский (NatSys Lab.,...
Как понять, что происходит на сервере? / Александр Крижановский (NatSys Lab.,...Как понять, что происходит на сервере? / Александр Крижановский (NatSys Lab.,...
Как понять, что происходит на сервере? / Александр Крижановский (NatSys Lab.,...
 
PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)
PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)
PostgreSQL as seen by Rubyists (Kaigi on Rails 2022)
 
Ground to ns3 - Basic wireless topology implementation
Ground to ns3 - Basic wireless topology implementationGround to ns3 - Basic wireless topology implementation
Ground to ns3 - Basic wireless topology implementation
 
Debugging linux issues with eBPF
Debugging linux issues with eBPFDebugging linux issues with eBPF
Debugging linux issues with eBPF
 
POLYTEDA PowerDRC/LVS overview
POLYTEDA PowerDRC/LVS overviewPOLYTEDA PowerDRC/LVS overview
POLYTEDA PowerDRC/LVS overview
 
Experiences in ELK with D3.js for Large Log Analysis and Visualization
Experiences in ELK with D3.js  for Large Log Analysis  and VisualizationExperiences in ELK with D3.js  for Large Log Analysis  and Visualization
Experiences in ELK with D3.js for Large Log Analysis and Visualization
 
Whose Stack Is It Anyway?
Whose Stack Is It Anyway?Whose Stack Is It Anyway?
Whose Stack Is It Anyway?
 
Super scaling singleton inserts
Super scaling singleton insertsSuper scaling singleton inserts
Super scaling singleton inserts
 
Make ARM Shellcode Great Again
Make ARM Shellcode Great AgainMake ARM Shellcode Great Again
Make ARM Shellcode Great Again
 
Docker Logging and analysing with Elastic Stack - Jakub Hajek
Docker Logging and analysing with Elastic Stack - Jakub Hajek Docker Logging and analysing with Elastic Stack - Jakub Hajek
Docker Logging and analysing with Elastic Stack - Jakub Hajek
 
Docker Logging and analysing with Elastic Stack
Docker Logging and analysing with Elastic StackDocker Logging and analysing with Elastic Stack
Docker Logging and analysing with Elastic Stack
 
IxVM on CML
IxVM on CMLIxVM on CML
IxVM on CML
 
MongoDB Days Silicon Valley: MongoDB and the Hadoop Connector
MongoDB Days Silicon Valley: MongoDB and the Hadoop ConnectorMongoDB Days Silicon Valley: MongoDB and the Hadoop Connector
MongoDB Days Silicon Valley: MongoDB and the Hadoop Connector
 
Varnish @ Velocity Ignite
Varnish @ Velocity IgniteVarnish @ Velocity Ignite
Varnish @ Velocity Ignite
 

More from NETFest

.NET Fest 2019. Николай Балакин. Микрооптимизации в мире .NET
.NET Fest 2019. Николай Балакин. Микрооптимизации в мире .NET.NET Fest 2019. Николай Балакин. Микрооптимизации в мире .NET
.NET Fest 2019. Николай Балакин. Микрооптимизации в мире .NETNETFest
 
.NET Fest 2019. Сергей Калинец. Efficient Microservice Communication with .NE...
.NET Fest 2019. Сергей Калинец. Efficient Microservice Communication with .NE....NET Fest 2019. Сергей Калинец. Efficient Microservice Communication with .NE...
.NET Fest 2019. Сергей Калинец. Efficient Microservice Communication with .NE...NETFest
 
.NET Fest 2019. Оля Гавриш. .NET Core 3.0 и будущее .NET
.NET Fest 2019. Оля Гавриш. .NET Core 3.0 и будущее .NET.NET Fest 2019. Оля Гавриш. .NET Core 3.0 и будущее .NET
.NET Fest 2019. Оля Гавриш. .NET Core 3.0 и будущее .NETNETFest
 
.NET Fest 2019. Оля Гавриш. Машинное обучение для .NET программистов
.NET Fest 2019. Оля Гавриш. Машинное обучение для .NET программистов.NET Fest 2019. Оля Гавриш. Машинное обучение для .NET программистов
.NET Fest 2019. Оля Гавриш. Машинное обучение для .NET программистовNETFest
 
.NET Fest 2019. Roberto Freato. Provisioning Azure PaaS fluently with Managem...
.NET Fest 2019. Roberto Freato. Provisioning Azure PaaS fluently with Managem....NET Fest 2019. Roberto Freato. Provisioning Azure PaaS fluently with Managem...
.NET Fest 2019. Roberto Freato. Provisioning Azure PaaS fluently with Managem...NETFest
 
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven DesignNETFest
 
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at WirexNETFest
 
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A....NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...NETFest
 
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixtureNETFest
 
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
.NET Fest 2019. Анатолий Колесник. Love, Death & F# TestsNETFest
 
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос....NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...NETFest
 
.NET Fest 2019. Roberto Freato. Azure App Service deep dive
.NET Fest 2019. Roberto Freato. Azure App Service deep dive.NET Fest 2019. Roberto Freato. Azure App Service deep dive
.NET Fest 2019. Roberto Freato. Azure App Service deep diveNETFest
 
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
.NET Fest 2019. Леонид Молотиевский. DotNet Core in productionNETFest
 
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com....NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com...NETFest
 
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real....NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...NETFest
 
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystemNETFest
 
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ....NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...NETFest
 
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali....NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...NETFest
 
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NETNETFest
 
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur....NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...NETFest
 

More from NETFest (20)

.NET Fest 2019. Николай Балакин. Микрооптимизации в мире .NET
.NET Fest 2019. Николай Балакин. Микрооптимизации в мире .NET.NET Fest 2019. Николай Балакин. Микрооптимизации в мире .NET
.NET Fest 2019. Николай Балакин. Микрооптимизации в мире .NET
 
.NET Fest 2019. Сергей Калинец. Efficient Microservice Communication with .NE...
.NET Fest 2019. Сергей Калинец. Efficient Microservice Communication with .NE....NET Fest 2019. Сергей Калинец. Efficient Microservice Communication with .NE...
.NET Fest 2019. Сергей Калинец. Efficient Microservice Communication with .NE...
 
.NET Fest 2019. Оля Гавриш. .NET Core 3.0 и будущее .NET
.NET Fest 2019. Оля Гавриш. .NET Core 3.0 и будущее .NET.NET Fest 2019. Оля Гавриш. .NET Core 3.0 и будущее .NET
.NET Fest 2019. Оля Гавриш. .NET Core 3.0 и будущее .NET
 
.NET Fest 2019. Оля Гавриш. Машинное обучение для .NET программистов
.NET Fest 2019. Оля Гавриш. Машинное обучение для .NET программистов.NET Fest 2019. Оля Гавриш. Машинное обучение для .NET программистов
.NET Fest 2019. Оля Гавриш. Машинное обучение для .NET программистов
 
.NET Fest 2019. Roberto Freato. Provisioning Azure PaaS fluently with Managem...
.NET Fest 2019. Roberto Freato. Provisioning Azure PaaS fluently with Managem....NET Fest 2019. Roberto Freato. Provisioning Azure PaaS fluently with Managem...
.NET Fest 2019. Roberto Freato. Provisioning Azure PaaS fluently with Managem...
 
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
 
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
 
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A....NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
 
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
 
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
 
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос....NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
 
.NET Fest 2019. Roberto Freato. Azure App Service deep dive
.NET Fest 2019. Roberto Freato. Azure App Service deep dive.NET Fest 2019. Roberto Freato. Azure App Service deep dive
.NET Fest 2019. Roberto Freato. Azure App Service deep dive
 
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
 
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com....NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
 
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real....NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
 
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
 
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ....NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
 
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali....NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
 
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
 
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur....NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
 

Recently uploaded

General AI for Medical Educators April 2024
General AI for Medical Educators April 2024General AI for Medical Educators April 2024
General AI for Medical Educators April 2024Janet Corral
 
microwave assisted reaction. General introduction
microwave assisted reaction. General introductionmicrowave assisted reaction. General introduction
microwave assisted reaction. General introductionMaksud Ahmed
 
Student login on Anyboli platform.helpin
Student login on Anyboli platform.helpinStudent login on Anyboli platform.helpin
Student login on Anyboli platform.helpinRaunakKeshri1
 
BASLIQ CURRENT LOOKBOOK LOOKBOOK(1) (1).pdf
BASLIQ CURRENT LOOKBOOK  LOOKBOOK(1) (1).pdfBASLIQ CURRENT LOOKBOOK  LOOKBOOK(1) (1).pdf
BASLIQ CURRENT LOOKBOOK LOOKBOOK(1) (1).pdfSoniaTolstoy
 
Holdier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdfHoldier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdfagholdier
 
Interactive Powerpoint_How to Master effective communication
Interactive Powerpoint_How to Master effective communicationInteractive Powerpoint_How to Master effective communication
Interactive Powerpoint_How to Master effective communicationnomboosow
 
Nutritional Needs Presentation - HLTH 104
Nutritional Needs Presentation - HLTH 104Nutritional Needs Presentation - HLTH 104
Nutritional Needs Presentation - HLTH 104misteraugie
 
Introduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsIntroduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsTechSoup
 
Unit-IV- Pharma. Marketing Channels.pptx
Unit-IV- Pharma. Marketing Channels.pptxUnit-IV- Pharma. Marketing Channels.pptx
Unit-IV- Pharma. Marketing Channels.pptxVishalSingh1417
 
Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)eniolaolutunde
 
Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111Sapana Sha
 
Activity 01 - Artificial Culture (1).pdf
Activity 01 - Artificial Culture (1).pdfActivity 01 - Artificial Culture (1).pdf
Activity 01 - Artificial Culture (1).pdfciinovamais
 
Ecosystem Interactions Class Discussion Presentation in Blue Green Lined Styl...
Ecosystem Interactions Class Discussion Presentation in Blue Green Lined Styl...Ecosystem Interactions Class Discussion Presentation in Blue Green Lined Styl...
Ecosystem Interactions Class Discussion Presentation in Blue Green Lined Styl...fonyou31
 
Beyond the EU: DORA and NIS 2 Directive's Global Impact
Beyond the EU: DORA and NIS 2 Directive's Global ImpactBeyond the EU: DORA and NIS 2 Directive's Global Impact
Beyond the EU: DORA and NIS 2 Directive's Global ImpactPECB
 
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...christianmathematics
 
Measures of Dispersion and Variability: Range, QD, AD and SD
Measures of Dispersion and Variability: Range, QD, AD and SDMeasures of Dispersion and Variability: Range, QD, AD and SD
Measures of Dispersion and Variability: Range, QD, AD and SDThiyagu K
 
APM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across SectorsAPM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across SectorsAssociation for Project Management
 
social pharmacy d-pharm 1st year by Pragati K. Mahajan
social pharmacy d-pharm 1st year by Pragati K. Mahajansocial pharmacy d-pharm 1st year by Pragati K. Mahajan
social pharmacy d-pharm 1st year by Pragati K. Mahajanpragatimahajan3
 

Recently uploaded (20)

Advance Mobile Application Development class 07
Advance Mobile Application Development class 07Advance Mobile Application Development class 07
Advance Mobile Application Development class 07
 
General AI for Medical Educators April 2024
General AI for Medical Educators April 2024General AI for Medical Educators April 2024
General AI for Medical Educators April 2024
 
microwave assisted reaction. General introduction
microwave assisted reaction. General introductionmicrowave assisted reaction. General introduction
microwave assisted reaction. General introduction
 
Student login on Anyboli platform.helpin
Student login on Anyboli platform.helpinStudent login on Anyboli platform.helpin
Student login on Anyboli platform.helpin
 
BASLIQ CURRENT LOOKBOOK LOOKBOOK(1) (1).pdf
BASLIQ CURRENT LOOKBOOK  LOOKBOOK(1) (1).pdfBASLIQ CURRENT LOOKBOOK  LOOKBOOK(1) (1).pdf
BASLIQ CURRENT LOOKBOOK LOOKBOOK(1) (1).pdf
 
Holdier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdfHoldier Curriculum Vitae (April 2024).pdf
Holdier Curriculum Vitae (April 2024).pdf
 
Interactive Powerpoint_How to Master effective communication
Interactive Powerpoint_How to Master effective communicationInteractive Powerpoint_How to Master effective communication
Interactive Powerpoint_How to Master effective communication
 
Nutritional Needs Presentation - HLTH 104
Nutritional Needs Presentation - HLTH 104Nutritional Needs Presentation - HLTH 104
Nutritional Needs Presentation - HLTH 104
 
Introduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsIntroduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The Basics
 
Unit-IV- Pharma. Marketing Channels.pptx
Unit-IV- Pharma. Marketing Channels.pptxUnit-IV- Pharma. Marketing Channels.pptx
Unit-IV- Pharma. Marketing Channels.pptx
 
Mattingly "AI & Prompt Design: The Basics of Prompt Design"
Mattingly "AI & Prompt Design: The Basics of Prompt Design"Mattingly "AI & Prompt Design: The Basics of Prompt Design"
Mattingly "AI & Prompt Design: The Basics of Prompt Design"
 
Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)
 
Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111
 
Activity 01 - Artificial Culture (1).pdf
Activity 01 - Artificial Culture (1).pdfActivity 01 - Artificial Culture (1).pdf
Activity 01 - Artificial Culture (1).pdf
 
Ecosystem Interactions Class Discussion Presentation in Blue Green Lined Styl...
Ecosystem Interactions Class Discussion Presentation in Blue Green Lined Styl...Ecosystem Interactions Class Discussion Presentation in Blue Green Lined Styl...
Ecosystem Interactions Class Discussion Presentation in Blue Green Lined Styl...
 
Beyond the EU: DORA and NIS 2 Directive's Global Impact
Beyond the EU: DORA and NIS 2 Directive's Global ImpactBeyond the EU: DORA and NIS 2 Directive's Global Impact
Beyond the EU: DORA and NIS 2 Directive's Global Impact
 
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
Explore beautiful and ugly buildings. Mathematics helps us create beautiful d...
 
Measures of Dispersion and Variability: Range, QD, AD and SD
Measures of Dispersion and Variability: Range, QD, AD and SDMeasures of Dispersion and Variability: Range, QD, AD and SD
Measures of Dispersion and Variability: Range, QD, AD and SD
 
APM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across SectorsAPM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across Sectors
 
social pharmacy d-pharm 1st year by Pragati K. Mahajan
social pharmacy d-pharm 1st year by Pragati K. Mahajansocial pharmacy d-pharm 1st year by Pragati K. Mahajan
social pharmacy d-pharm 1st year by Pragati K. Mahajan
 

.NET Fest 2019. Łukasz Pyrzyk. Daily Performance Fuckups

  • 2. ŁUKASZ PYRZYK • Co-founder of Dotnetos • Senior Full Stack Cloud Developer at Sonova/JCommerce • Tweets as @lukaszpyrzyk
  • 3. AGENDA • Assuming performance improvement by looking at code which may look faster • Decompiling our code with Sharplab.io to understand how optimizer can predict our ideas • Story of the releasing product in debug mode • Relying on the debug code behaviours and object state • Surprising behaviours of tiered compilation • Optimizing code with ArrayPool and ETW events • Simple, but valuable optimization of the CosmosDB which come from official documentations • Steaming network data with ASP.NET • Pitfalls of optimizing code without taking a wider perspective on the problem
  • 5.
  • 6. public void XOR(ref int x, ref int y) { x = x ^ y; y = x ^ y; x = x ^ y; } - No temp int variable - int is 4 bytes, so it saves 4 bytes - Assembly has XOR operation, so it’s 1:1, so it’s fast @lukaszpyrzyk
  • 7. 00007ffc`d7459170 XOR(Int32 ByRef, Int32 ByRef) IL_0000: ldarg.1, IL_0001: ldarg.1 IL_0002: ldind.i4, IL_0003: ldarg.2 IL_0004: ldind.i4, IL_0005: xor IL_0006: stind.i4 00007ffc`d7459170 418b00 mov eax,dword ptr [r8] 00007ffc`d7459173 3102 xor dword ptr [rdx],eax IL_0007: ldarg.2, IL_0008: ldarg.1 IL_0009: ldind.i4, IL_000a: ldarg.2 IL_000b: ldind.i4 IL_000c: xor IL_000d: stind.i4 00007ffc`d7459175 8b02 mov eax,dword ptr [rdx] 00007ffc`d7459177 413100 xor dword ptr [r8],eax IL_000e: ldarg.1, IL_000f: ldarg.1 IL_0010: ldind.i4, IL_0011: ldarg.2 IL_0012: ldind.i4 IL_0013: xor IL_0014: stind.i4 00007ffc`d745917a 418b00 mov eax,dword ptr [r8] 00007ffc`d745917d 3102 xor dword ptr [rdx],eax IL_0015: ret 00007ffc`d745917f c3 ret
  • 8. 00007ffc`d7459170 TempVariable(Int32 ByRef, Int32 ByRef) IL_0000: ldarg.1 IL_0001: ldind.i4 IL_0002: stloc.0 00007ffc`d7459170 8b02 mov eax,dword ptr [rdx] IL_0003: ldarg.1 IL_0004: ldarg.2 IL_0005: ldind.i4 IL_0006: stind.i4 00007ffc`d7459172 418b08 mov ecx,dword ptr [r8] 00007ffc`d7459175 890a mov dword ptr [rdx],ecx IL_0007: ldarg.2 IL_0008: ldloc.0 IL_0009: stind.i4 00007ffc`d7459177 418900 mov dword ptr [r8],eax IL_000a: ret 00007ffc`d745917a c3 ret
  • 9. 00007ff9`b7092140 418b00 mov eax,dword ptr [r8] 00007ff9`b7092143 3102 xor dword ptr [rdx],eax 00007ff9`b7092145 8b02 mov eax,dword ptr [rdx] 00007ff9`b7092147 413100 xor dword ptr [r8],eax 00007ff9`b709214a 418b00 mov eax,dword ptr [r8] 00007ff9`b709214d 3102 xor dword ptr [rdx],eax 00007ff9`b709214f c3 ret XOR 00007ff9`b70b2140 8b02 mov eax,dword ptr [rdx] 00007ff9`b70b2142 418b08 mov ecx,dword ptr [r8] 00007ff9`b70b2145 890a mov dword ptr [rdx],ecx 00007ff9`b70b2147 418900 mov dword ptr [r8],eax 00007ff9`b70b214a c3 ret TempVariable @lukaszpyrzyk BenchmarkDotNet=v0.11.5, OS=Windows 10.0.16299.1146 (1709/FallCreatorsUpdate/Redstone3) Intel Core i5-7200U CPU 2.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores Frequency=2648437 Hz, Resolution=377.5812 ns, Timer=TSC
  • 10. Method Mean Error StdDev Median XOR 2.8275 ns 0.0615 ns 0.0575 ns 2.8419 ns @lukaszpyrzyk BenchmarkDotNet=v0.11.5, OS=Windows 10.0.16299.1146 (1709/FallCreatorsUpdate/Redstone3) Intel Core i5-7200U CPU 2.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores Frequency=2648437 Hz, Resolution=377.5812 ns, Timer=TSC
  • 11. Method Mean Error StdDev Median XOR 2.8275 ns 0.0615 ns 0.0575 ns 2.8419 ns TempVariabl e 0.0114 ns 0.0131 ns 0.0123 ns 0.0000 ns @lukaszpyrzyk The method duration is indistinguishable from the empty method duration Requires Benchmarkdotnet v0.11.2+
  • 12. public void AddAndSubtract(ref int x, ref int y) { x = x + y; y = x - y; x = x - y; } @lukaszpyrzyk
  • 13. Method Mean Error StdDev Median XOR 2.8275 ns 0.0615 ns 0.0575 ns 2.8419 ns TempVariabl e 0.0114 ns 0.0131 ns 0.0123 ns 0.0000 ns AddAndSubtrac t 2.8454 ns 0.0691 ns 0.0646 ns 2.8798 ns @lukaszpyrzyk BenchmarkDotNet=v0.11.5, OS=Windows 10.0.16299.1146 (1709/FallCreatorsUpdate/Redstone3) Intel Core i5-7200U CPU 2.50GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores Frequency=2648437 Hz, Resolution=377.5812 ns, Timer=TSC
  • 14. Method Runtime Mean Error StdDev Median TempVariable Clr 0.0022 ns 0.0067 ns 0.0062 ns 0.0000 ns AddAndSubtract Clr 3.0518 ns 0.0767 ns 0.0641 ns 3.0383 ns XOR Clr 2.9713 ns 0.0636 ns 0.0594 ns 2.9579 ns TempVariable Core 0.0199 ns 0.0264 ns 0.0418 ns 0.0000 ns AddAndSubtract Core 3.0355 ns 0.0953 ns 0.1135 ns 3.0258 ns XOR Core 2.8102 ns 0.0778 ns 0.0728 ns 2.7733 ns TempVariable Mono 0.4762 ns 0.0937 ns 0.2704 ns 0.3619 ns AddAndSubtract Mono 2.9212 ns 0.1042 ns 0.1115 ns 2.8869 ns XOR Mono 2.8912 ns 0.0686 ns 0.0573 ns 2.8840 ns
  • 16. public void M() { int x = 4096, y = 8192; x = x ^ y; y = x ^ y; x = x ^ y; Console.WriteLine(x); Console.WriteLine(y); } @lukaszpyrzyk
  • 17. public void M() { int x = 4096, y = 8192; int temp = x; x = y; y = temp; Console.WriteLine(x); Console.WriteLine(y); } @lukaszpyrzyk
  • 19. IT IS THE SAME! @lukaszpyrzyk
  • 22. ISSUE #2 RELEASING PRODUCT IN DEBUG MODE @lukaszpyrzyk
  • 25. PREVIOUS YAMLDOTNET BENCHMARKS foreach(var test in tests) { Console.Write("{0}t{1}t", adapterName, test.GetType().Name); var graph = test.Graph; RunTest(serializer, graph); // warmup if (!Stopwatch.IsHighResolution) Console.Error.WriteLine("Stopwatch is not high resolution!"); var timer = Stopwatch.StartNew(); for (var i = 0; i < iterations; ++i) RunTest(serializer, graph); var duration = timer.Elapsed; Console.WriteLine("{0}", duration.TotalMilliseconds / iterations); }
  • 26. ATTEMP WITH BENCHMARKDOTNET [MemoryDiagnoser] public class ReceiptTest { private readonly Receipt _receipt = new Receipt(); private readonly StringWriter _buffer = new StringWriter(); private readonly ISerializer _serializer = new SerializerBuilder() .WithNamingConvention(new CamelCaseNamingConvention()) .Build(); [Benchmark] public void Serialize() { _serializer.Serialize(_buffer, _receipt.Graph); } }
  • 27. dotnet run –c Release // Validating benchmarks: Assembly YamlDotNet.PerformanceTests.vlatest which defines benchmarks references non-optimized YamlDotNet - If you own this dependency, please, build it in RELEASE. - If you don't, you can create custom config with DontFailOnError to disable our custom policy and allow this benchmark to run.
  • 28. PROBLEM New csproj format doesn’t have the same behaviour as the old one. Configurations like Release-* don’t inherit from Release configuration.
  • 29. FIX <PropertyGroup Condition=" '$(Configuration)' == 'Release-Signed' Or '$(Configuration)' == 'Release-Unsigned' "> <DefineConstants>$(DefineConstants);RELEASE;TRACE</DefineConstants> <DebugSymbols>false</DebugSymbols> <DebugType>portable</DebugType> <Optimize>true</Optimize> </PropertyGroup>
  • 30. FIX ----------------------------------------------------------------------------------- | | Mean | Error | StdDev | Gen0 | Gen1 | Allocated | ----------------------------------------------------------------------------------- | v1.2.1 | 128.7 us | 1.285 us | 1.202 us | 5.8594 | 0.2441 | 23.66 KB | | v2.2.0 | 240.6 us | 3.467 us | 3.243 us | 18.0664 | 0.4883 | 60.03 KB | | v2.3.0 | 307.9 us | 6.112 us | 10.21 us | 20.0195 | 0.4883 | 67.32 KB | | v3.8.0 | 292.2 us | 4.225 us | 3.952 us | 21.4844 | 0.4883 | 70.82 KB | | v4.0.0 | 283.2 us | 3.075 us | 2.876 us | 22.9492 | 0.4883 | 74.26 KB | | v5.2.1 | 539.5 us | 5.710 us | 5.062 us | 8.7891 | 0.9766 | 30.82 KB | | vlatest | 145.8 us | 1.671 us | 1.563 us | 8.3008 | 0.4883 | 30.7 KB | ----------------------------------------------------------------------------------
  • 34. @lukaszpyrzyk BUFFERING A FILE Github blob Server User http://dotnet.microsoft.com/download/
  • 35. @lukaszpyrzyk BUFFERING A FILE public async Task<IActionResult> WithBuffering() { var request = new HttpRequestMessage(HttpMethod.Get, "dotnet/corefx/archive/v2.2.0-preview3.zip"); var response = await _client.Client.SendAsync(request); var stream = await response.Content.ReadAsStreamAsync(); var contentType = response.Content.Headers.ContentType.MediaType; return new FileStreamResult(stream, contentType); }
  • 37. @lukaszpyrzyk BUFFERING A FILE public async Task<IActionResult> WithoutBuffering() { var request = new HttpRequestMessage(HttpMethod.Get, "dotnet/corefx/archive/v2.2.0-preview3.zip"); var response = await _client.Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); var stream = await response.Content.ReadAsStreamAsync(); var contentType = response.Content.Headers.ContentType.MediaType; return new FileStreamResult(stream, contentType); }
  • 39. @lukaszpyrzyk BUFFERING A FILE public async Task<Stream> Stream() { var request = new HttpRequestMessage(HttpMethod.Get, "dotnet/corefx/archive/v2.2.0-preview3.zip"); var response = await _client.Client.GetStreamAsync(request.RequestUri); return response; }
  • 40. ISSUE #4 RELYING ON THE OBJECT STATE
  • 41. static void Main(string[] args) { var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100); Console.WriteLine("Timer started?"); GC.Collect(); Console.Read(); } CODE
  • 42. dotnet run -c Debug 14/10/2019 18:43:22 Timer started? 14/10/2019 18:43:22 14/10/2019 18:43:22 14/10/2019 18:43:22 […] DEBUG
  • 43. dotnet run -c Release Timer started? 14/10/2019 18:48:56 RELEASE
  • 44. EAGER ROOT COLLECTION IT IS A JUST-IN-TIME COMPILER OPTIMIZATION WHICH MAKES LOCAL REFERENCES IRRELEVANT AFTER THEIR LAST USAGE
  • 45. KEEP ALIVE static void Main(string[] args) { var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100); Console.WriteLine("Timer started?"); GC.Collect(); Console.Read(); GC.KeepAlive(timer); }
  • 46. CALLING DISPOSE static void Main(string[] args) { var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100); Console.WriteLine("Timer started?"); GC.Collect(); Console.Read(); timer.Dispose(); }
  • 47. CALLING DISPOSE static void Main(string[] args) { using (var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100)) { Console.WriteLine("Timer started?"); GC.Collect(); Console.Read(); } }
  • 49. CALLING DISPOSE static void Main(string[] args) { using var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100); Console.WriteLine("Timer started?"); GC.Collect(); Console.Read(); }
  • 50. CALLING DISPOSE [NullableContext(1)] [Nullable(0)] public sealed class Timer : MarshalByRefObject, IAsyncDisposable, Idisposable { /// <summary>Releases all resources used by the current instance of <see cref="T:System.Threading.Timer" />.</summary> /// <returns>A <see cref="T:System.Threading.Tasks.ValueTask" /> that completes when all work associated with the timer has ceased.</returns> public ValueTask DisposeAsync(); }
  • 51. CALLING DISPOSE static async Task Main(string[] args) { await using var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100); Console.WriteLine("Timer started?"); GC.Collect(); Console.Read(); }
  • 52.
  • 53. static void Main(string[] args) { var timer = new Timer(x => Console.WriteLine(DateTime.UtcNow), null, 0, 100); Console.WriteLine("Timer started?"); GC.Collect(); Console.Read(); } CODE
  • 54. dotnet run -c Release Timer started? 16/10/2019 16:36:51 16/10/2019 16:36:51 16/10/2019 16:36:51 16/10/2019 16:36:51 16/10/2019 16:36:51 16/10/2019 16:36:51 16/10/2019 16:36:51 [..] RELEASE
  • 55. WHAT?
  • 57. .NET Core version Tiered compilation 2.0 None 2.1 Optional 3.0 Default
  • 60.
  • 61. TIERED COMPILATION CAN INFLUENCE THE PROFILING AND BENCHMARKING RESULTS. IT CAN CHANGE RESULTS OF SAMPLES FROM BOOKS OR BLOG POSTS @lukaszpyrzyk
  • 62. ISSUE #5 NOT USING ETW EVENTS
  • 63. private static async Task Default() { var buffer = new byte[8 * 1024]; for (int i = 0; i < Iterations; i++) { foreach (var file in Directory.EnumerateFiles("images")) { var fileInfo = new FileInfo(file); var array = new byte[fileInfo.Length]; await using var stream = File.OpenRead(file); await ReadStreamToArray(fileInfo, stream, buffer, array); } } }
  • 64.
  • 65. CommandLine: "C:devDPFSrcDPF.ArrayPoolbinReleasenetcoreapp3.0DPF.Arra yPool.exe" Runtime Version: V 4.0.30319.0 (built on 13/09/2019 01:02:04) CLR Startup Flags: None Total CPU Time: 11,368 msec Total GC CPU Time: 19 msec Total Allocs : 1,263.242 MB GC CPU MSec/MB Alloc : 0.015 MSec/MB Total GC Pause: 20.5 msec % Time paused for Garbage Collection: 0.3% % CPU Time spent Garbage Collecting: 0.2% Max GC Heap Size: 145.235 MB Peak Process Working Set: 170.570 MB Peak Virtual Memory Usage: 2,199,714.988 MB
  • 67.
  • 68. var arrayPool = ArrayPool<byte>.Shared; var buffer = arrayPool.Rent(8 * 1024); try { for (int i = 0; i < Iterations; i++) { foreach (var file in Directory.EnumerateFiles("images")) { var fileInfo = new FileInfo(file); var array = arrayPool.Rent(Convert.ToInt32(fileInfo.Length)); try { await using var stream = File.OpenRead(file); await ReadStreamToArray(fileInfo, stream, buffer, array); } finally { arrayPool.Return(array); } } } } finally { arrayPool.Return(buffer); }
  • 69.
  • 70. CommandLine: "C:devDPFSrcDPF.ArrayPoolbinReleasenetcoreapp3.0DPF.Arra yPool.exe" Runtime Version: V 4.0.30319.0 (built on 13/09/2019 01:02:04) CLR Startup Flags: None Total CPU Time: 12,527 msec Total GC CPU Time: 12 msec Total Allocs : 1,014.148 MB GC CPU MSec/MB Alloc : 0.012 MSec/MB Total GC Pause: 25.1 msec % Time paused for Garbage Collection: 0.3% % CPU Time spent Garbage Collecting: 0.1% Max GC Heap Size: 146.111 MB Peak Process Working Set: 158.175 MB Peak Virtual Memory Usage: 2,199,715.676 MB
  • 71. Remarks Using the ArrayPool<T> class to rent and return buffers (using the Rent and Return methods) improve performance in situations where arrays are created and destroyed frequently, resulting significant memory pressure on the garbage collector.
  • 72.
  • 73.
  • 75. var biggestFile = Directory.GetFiles("images").Select(x => new FileInfo(x)).Select(x => x.Length).Max(); var arrayPool = ArrayPool<byte>.Create(maxArrayLength: Convert.ToInt32(biggestFile), maxArraysPerBucket: 1); var buffer = arrayPool.Rent(8 * 1024); try { for (int i = 0; i < Iterations; i++) { foreach (var file in Directory.EnumerateFiles("images")) { var fileInfo = new FileInfo(file); var array = arrayPool.Rent(Convert.ToInt32(fileInfo.Length)); try { await using var stream = File.OpenRead(file); await ReadStreamToArray(fileInfo, stream, buffer, array); } finally { arrayPool.Return(array); } } } } finally { arrayPool.Return(buffer); }
  • 76.
  • 77. CommandLine: "C:devDPFSrcDPF.ArrayPoolbinReleasenetcoreapp3.0DPF.Arra yPool.exe" Runtime Version: V 4.0.30319.0 (built on 13/09/2019 01:02:04) CLR Startup Flags: None Total CPU Time: 11,358 msec Total GC CPU Time: 8 msec Total Allocs : 58.261 MB GC CPU MSec/MB Alloc : 0.137 MSec/MB Total GC Pause: 11.3 msec % Time paused for Garbage Collection: 0.2% % CPU Time spent Garbage Collecting: 0.1% Max GC Heap Size: 37.899 MB Peak Process Working Set: 51.962 MB Peak Virtual Memory Usage: 2,199,574.643 MB
  • 78.
  • 79. Allocated bytes Max GC Heap Size New arrays 1,263.242 MB 145.235 MB Shared ArrayPool 1,014.148 MB 146.111 MB Custom ArrayPool<byte> 58.261 MB 37.899 MB
  • 80. TIP ARRAYPOOL.SHARED ALLOCATES MEMORY IF IT NEEDS TO RENT ARRAY BIGGER THAN 2^20 BYTES (1MB) @lukaszpyrzyk
  • 81. ISSUE #6 RELYING ON THE LIBRARY AND CROSS PLATFORM FEATURES @lukaszpyrzyk
  • 82. public class TelemetryEntry { public DateTimeOffset Timestamp { get; set; } public int UserId { get; set; } } @lukaszpyrzyk
  • 83. [Route("[controller]")] [ApiController] public class TelemetryController : Controller { [HttpPut] public async Task<IActionResult> Insert([FromServices] DataStorageService db) { var entry = CreateEntry(); await db.Insert(entry); return NoContent(); } } @lukaszpyrzyk
  • 85. public class DataStorageService { private readonly DataStorageServiceOptions _options; private readonly DocumentClient _client; public SlowDataStorageService(DataStorageServiceOptions options) { _options = options; _client = new DocumentClient(options.Endpoint, options.ApiKey); _client.CreateDatabaseIfNotExistsAsync(new Database { Id = options.DatabaseName }).GetAwaiter().GetResult(); _client.CreateDocumentCollectionIfNotExistsAsync( UriFactory.CreateDatabaseUri(options.DatabaseName), new DocumentCollection { Id = options.CollectionName }) .GetAwaiter().GetResult(); } } GetAwaiter().GetResult(); GetAwaiter().GetResult() @lukaszpyrzyk
  • 86. public async Task Insert(TelemetryEntry telemetryEntry) { var collectionUri = UriFactory.CreateDocumentCollectionUri(_options.DatabaseName, _options.CollectionName); await _client.CreateDocumentAsync(collectionUri, telemetryEntry); } @lukaszpyrzyk
  • 87. public void ConfigureServices(IServiceCollection services) { var dbOptions = GetOptions(); services.AddSingleton(dbOptions); services.AddTransient<DataStorageService>(); } @lukaszpyrzyk AddTransient
  • 88. TESTING – NO DOCS Running 30s test @ http://localhost:5000/telemetry/insert/slow 1 threads and 1 connections Thread Stats Avg Stdev Max +/- Stdev Latency 876.89ms 45.82ms 993.87ms 76.47% Req/Sec 0.88 0.33 1.00 88.24% 34 requests in 30.07s, 2.69KB read Requests/sec: 1.13 Transfer/sec: 91.57B @lukaszpyrzyk
  • 90. public class AsyncLazy<T> : Lazy<Task<T>> { public AsyncLazy(Func<Task<T>> valueFactory) : base(valueFactory) { } } @lukaszpyrzyk
  • 91. public class DataStorageService { private readonly AsyncLazy<DocumentClient> _clientFactory; private readonly Uri _collectionUri; public DataStorageService(DataStorageServiceOptions options) { _collectionUri = UriFactory.CreateDocumentCollectionUri(options.DatabaseName, options.CollectionName); _clientFactory = new AsyncLazy<DocumentClient>(async () => { var client = new DocumentClient(options.Endpoint, options.ApiKey); await InitialDatabase(client, options); }); } } @lukaszpyrzyk
  • 92. public async Task Insert(TelemetryEntry telemetryEntry) { var client = await _clientFactory.Value; await client.CreateDocumentAsync(_collectionUri, telemetryEntry); } @lukaszpyrzyk
  • 93. public void ConfigureServices(IServiceCollection services) { var dbOptions = GetOptions(); services.AddSingleton(dbOptions); services.AddSingleton<DataStorageService>(); } @lukaszpyrzyk
  • 94. TESTING - OPTIMIZATIONS @lukaszpyrzyk 0 2 4 6 8 10 12 No docs Cleaning & singleton Requests per second
  • 95. _clientFactory = new AsyncLazy<DocumentClient>(async () => { var client = new DocumentClient(options.Endpoint, options.ApiKey, new ConnectionPolicy { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Protocol.Tcp }); await InitialDatabase(client, options); }); @lukaszpyrzyk
  • 96. TESTING – DIRECT / TCP @lukaszpyrzyk 0 2 4 6 8 10 12 14 No docs Cleaning & singleton Direct / TCP Requests per second
  • 97. THE GONEEXCEPTION STORY • Microservices • CosmosDB • Migration to the Direct/TCP connection policy, feature toggle • Thousands of the GoneException saying “The requested resource is no longer available at the server” • We have a bug!!! • Race condition? Dispose? Network down? Firewall? @lukaszpyrzyk
  • 101. THE GONEEXCEPTION STORY GoneException(“The requested resource is no longer available at the server”) might be PlatformNotSupportedException(); @lukaszpyrzyk
  • 103. ISSUE #7 LET’S OPTIMIZE IT @lukaszpyrzyk
  • 104. THE BUSINESS PROBLEM • This is very important for our company • It’s PoC • Please make it ASAP • Performance doesn’t matter • Don’t spend to much time on it • Keep clean and easy to understand for another developers @lukaszpyrzyk
  • 105. public ulong SecretAlgorithm(ulong n) { if (n == 1 || n == 2) return 1; return SecretAlgorithm(n - 2) + SecretAlgorithm(n - 1); } @lukaszpyrzyk
  • 106. public ulong Fibonacci(ulong n) { if (n == 1 || n == 2) return 1; return Fibonacci(n - 2) + Fibonacci(n - 1); } @lukaszpyrzyk
  • 107. THE BUSINESS PROBLEM • It works • It is simple @lukaszpyrzyk
  • 108. THE BUSINESS PROBLEM Make it faster! @lukaszpyrzyk
  • 109. THE BUSINESS PROBLEM What kind of optimizations techniques do I know? @lukaszpyrzyk
  • 110. public ulong Fibonacci(ulong n) { if (n == 1 || n == 2) return 1; var a = Task.Run(() => Fibonacci(n - 2)); var b = Task.Run(() => Fibonacci(n - 1)); Task.WaitAll(a, b); return a.Result + b.Result; } @lukaszpyrzyk
  • 111. @lukaszpyrzyk 3,130.90 230,628.90 0.00 50,000.00 100,000.00 150,000.00 200,000.00 250,000.00 300,000.00 Default Recursive TPL n = 15, ns 47,396,067.95 4,621,743,140.75 0.00 1,000,000,000.00 2,000,000,000.00 3,000,000,000.00 4,000,000,000.00 5,000,000,000.00 6,000,000,000.00 Default Recursive TPL n = 35, ns
  • 112. public ulong Fibonacci(ulong n) { if (n == 1 || n == 2) return 1; var a = Task.Run(() => FibonacciImplementation(n - 2)); var b = Task.Run(() => FibonacciImplementation(n - 1)); Task.WaitAll(a, b); return a.Result + b.Result; } private ulong FibonacciImplementation(ulong n) { if (n == 1 || n == 2) return 1; return Recursive(n - 2) + Recursive(n - 1); } @lukaszpyrzyk
  • 116. public static ulong Recursive(ulong n) { Console.WriteLine($"Calculating Fibonacci for {n}"); if (n == 1 || n == 2) return 1; return Recursive(n - 2) + Recursive(n - 1); } @lukaszpyrzyk
  • 117. Fibonacci(5); Calculating Fibonacci for 5 Calculating Fibonacci for 3 Calculating Fibonacci for 1 Calculating Fibonacci for 2 Calculating Fibonacci for 4 Calculating Fibonacci for 2 Calculating Fibonacci for 3 Calculating Fibonacci for 1 Calculating Fibonacci for 2 @lukaszpyrzyk
  • 118. WE DO THE SAME JOB SEVERAL TIMES
  • 119. MEMOIZATION It is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again @lukaszpyrzyk
  • 120. MEMOIZATION public ulong Fibonacci(ulong n) { if (n == 1 || n == 2) return 1; var results = new ulong[n]; results[0] = 1; results[1] = 1; return FibWithMemoization(n, results); } @lukaszpyrzyk
  • 121. MEMOIZATION private static ulong FibWithMemoization(ulong n, ulong[] results) { var current = n - 1; var previous = current - 1; var beforePrevious = previous - 1; if (results[beforePrevious] == 0) results[beforePrevious] = FibWithMemoization(previous, results); if (results[previous] == 0) results[previous] = FibWithMemoization(current, results); results[current] = results[beforePrevious] + results[previous]; return results[n - 1]; } @lukaszpyrzyk
  • 124. THE BUSINESS PROBLEM WHAT WE MISSED? @lukaszpyrzyk
  • 125. public ulong Fibonacci(ulong n) { if (n == 1 || n == 2) return 1; ulong a = 1, b = 1; for (ulong i = 2; i < n; i++) { ulong temp = a + b; a = b; b = temp; } return b; } @lukaszpyrzyk
  • 128. TIP BEFORE DOING OPTIMIZATIONS MAKE SURE THAT CURRENT SOLUTION STILL FITS @lukaszpyrzyk
  • 129. SUMMARY • We should always validate our performance improvements by measurement • Releasing product in debug sounds funny, but there are real cases where by mistake debug code was shipped to the clients • Tiered compilation is new in .NET world and we need get used to it. It is a good idea to disable tierec compilation for profiling and benchmarking or get code warm • Reading documentation and API notes may give you easy performance boost, for example by making CosmosDB client singleton with Direct connection or using HttpCompletionOption • ETW event are a great collection of knowledge about our application, for example about ArrayPool usage • Before doing code optimizations we should understand how it is used
  • 130. LINKS • Konrad Kokosa - Pro .NET Memory Management, https://prodotnetmemory.com/ • Andrey Akinshin - Pro .NET Benchmarking, https://www.apress.com/gp/book/9781484249406 • https://github.com/lukasz-pyrzyk/DailyPerformancePitfalls • https://docs.microsoft.com/en-us/azure/cosmos-db/performance-tips • https://docs.microsoft.com/en-us/azure/cosmos-db/sql-api-sql-query- metricshttp://www.tugberkugurlu.com/archive/efficiently-streaming-large-http-responses- with-httpclient • https://github.com/davidfowl/AspNetCoreDiagnosticScenarios • https://wojciechnagorski.com/2018/12/how-i-improved-the-yamldotnet-performance-by- 370/ • https://github.com/aaubry/YamlDotNet/pull/356 @lukaszpyrzyk
  • 131. 10-11 October 2019 Warsaw - Poland dotnetos.org

Editor's Notes

  1. in real life and big applications, it’s not always possible to use BenchmarkDotNet. In this case, Debug build can be a source of huge problems in the performance analysis.