akamsteeg / AtleX.HaveIBeenPwned

A modern, fully async, high performance, .NET client library for the API of HaveIBeenPwned.com
https://www.nuget.org/packages/AtleX.HaveIBeenPwned/
MIT License
5 stars 0 forks source link

Optimize performance by eliminating the intermediate MemoryStream in HaveIBeenPwnedClient #36

Closed akamsteeg closed 5 years ago

akamsteeg commented 5 years ago

In HaveIBeenPwnedClient.GetAsync(HttpRequestMessage, CancellationToken), a new MemoryStream is created for every request.

https://github.com/akamsteeg/AtleX.HaveIBeenPwned/blob/88c3561bbe0d60aa5cdd5f877c953b18181b4d7d/src/AtleX.HaveIBeenPwned/HaveIBeenPwnedClient.cs#L535..L570

We can avoid the copy of the response stream to the MemoryStream by just returning the output HttpResponseMesssage and parse the content Stream directly,

Before:


BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i7-8850H CPU 2.60GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET Core SDK=3.0.100
  [Host]   : .NET Core 2.1.13 (CoreCLR 4.6.28008.01, CoreFX 4.6.28008.01), 64bit RyuJIT
  ShortRun : .NET Core 2.1.13 (CoreCLR 4.6.28008.01, CoreFX 4.6.28008.01), 64bit RyuJIT

Job=ShortRun  IterationCount=3  LaunchCount=1  
WarmupCount=3  
Method Toolchain Mean Error StdDev Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated
GetAllBreachesAsync .NET Core 2.1 76.853 us 8.670 us 0.4752 us 1.00 0.00 8.6670 - - 40.18 KB
GetAllBreachesAsync .NET Core 3.0 68.938 us 4.819 us 0.2642 us 0.90 0.00 8.5449 0.6104 - 39.63 KB
GetAllBreachesAsync net472 139.614 us 57.631 us 3.1589 us 1.82 0.05 10.2539 0.4883 - 47.47 KB
GetBreachesAsync .NET Core 2.1 11.193 us 1.770 us 0.0970 us 1.00 0.00 2.1210 - - 9.84 KB
GetBreachesAsync .NET Core 3.0 8.632 us 2.390 us 0.1310 us 0.77 0.01 2.1057 0.0153 - 9.73 KB
GetBreachesAsync net472 26.994 us 6.851 us 0.3755 us 2.41 0.05 3.1128 - - 14.44 KB
GetBreachesAsync_BreachMode .NET Core 2.1 11.142 us 2.480 us 0.1359 us 1.00 0.00 2.1210 - - 9.84 KB
GetBreachesAsync_BreachMode .NET Core 3.0 8.801 us 2.342 us 0.1284 us 0.79 0.01 2.1057 0.0153 - 9.73 KB
GetBreachesAsync_BreachMode net472 26.857 us 11.686 us 0.6406 us 2.41 0.08 3.1128 - - 14.43 KB
GetPastesAsync .NET Core 2.1 127.596 us 100.543 us 5.5111 us 1.00 0.00 8.3008 0.2441 - 39.03 KB
GetPastesAsync .NET Core 3.0 114.201 us 24.474 us 1.3415 us 0.90 0.03 8.1787 0.4883 - 37.92 KB
GetPastesAsync net472 197.640 us 27.619 us 1.5139 us 1.55 0.08 10.2539 0.2441 - 47.98 KB
IsPwnedPasswordAsync .NET Core 2.1 72.657 us 9.248 us 0.5069 us 1.00 0.00 30.0293 0.1221 - 139.02 KB
IsPwnedPasswordAsync .NET Core 3.0 61.045 us 11.344 us 0.6218 us 0.84 0.01 29.7852 5.8594 - 137.45 KB
IsPwnedPasswordAsync net472 159.115 us 6.942 us 0.3805 us 2.19 0.02 31.7383 3.6621 - 146.78 KB

After:


BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i7-8850H CPU 2.60GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET Core SDK=3.0.100
  [Host]   : .NET Core 2.1.13 (CoreCLR 4.6.28008.01, CoreFX 4.6.28008.01), 64bit RyuJIT
  ShortRun : .NET Core 2.1.13 (CoreCLR 4.6.28008.01, CoreFX 4.6.28008.01), 64bit RyuJIT

Job=ShortRun  IterationCount=3  LaunchCount=1  
WarmupCount=3  
Method Toolchain Mean Error StdDev Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated
GetAllBreachesAsync .NET Core 2.1 86.835 us 87.5170 us 4.7971 us 1.00 0.00 7.3242 0.4883 - 33.84 KB
GetAllBreachesAsync .NET Core 3.0 68.901 us 2.5200 us 0.1381 us 0.80 0.05 7.2021 0.4883 - 33.29 KB
GetAllBreachesAsync net472 83.136 us 13.0081 us 0.7130 us 0.96 0.06 7.5684 - - 35.02 KB
GetBreachesAsync .NET Core 2.1 10.675 us 4.4393 us 0.2433 us 1.00 0.00 2.0752 - - 9.63 KB
GetBreachesAsync .NET Core 3.0 7.950 us 0.6502 us 0.0356 us 0.74 0.02 2.0599 0.0305 - 9.52 KB
GetBreachesAsync net472 13.839 us 0.7638 us 0.0419 us 1.30 0.03 2.4109 - - 11.14 KB
GetBreachesAsync_BreachMode .NET Core 2.1 10.607 us 0.5307 us 0.0291 us 1.00 0.00 2.0752 - - 9.63 KB
GetBreachesAsync_BreachMode .NET Core 3.0 8.438 us 15.2459 us 0.8357 us 0.80 0.08 2.0599 0.0305 - 9.52 KB
GetBreachesAsync_BreachMode net472 13.644 us 2.7284 us 0.1496 us 1.29 0.01 2.4109 - - 11.14 KB
GetPastesAsync .NET Core 2.1 131.078 us 100.7229 us 5.5210 us 1.00 0.00 7.0801 0.2441 - 32.77 KB
GetPastesAsync .NET Core 3.0 126.946 us 176.8919 us 9.6960 us 0.97 0.06 6.8359 0.3662 - 31.66 KB
GetPastesAsync net472 134.279 us 121.2541 us 6.6463 us 1.02 0.02 7.3242 - - 33.97 KB
IsPwnedPasswordAsync .NET Core 2.1 70.155 us 0.1897 us 0.0104 us 1.00 0.00 25.6348 - - 118.14 KB
IsPwnedPasswordAsync .NET Core 3.0 59.009 us 8.0837 us 0.4431 us 0.84 0.01 25.2686 4.1504 - 116.58 KB
IsPwnedPasswordAsync net472 94.822 us 3.8843 us 0.2129 us 1.35 0.00 26.7334 4.3945 - 123.58 KB
akamsteeg commented 5 years ago

Fixed in 4e71017d and 546117b9.