Skip to content

Instantly share code, notes, and snippets.

@AustinWise
Last active August 27, 2024 16:26
Show Gist options
  • Save AustinWise/1e635a5c7a07e6052c69e720f46ec5a7 to your computer and use it in GitHub Desktop.
Save AustinWise/1e635a5c7a07e6052c69e720f46ec5a7 to your computer and use it in GitHub Desktop.
Benchmarking downloading a file with HttpClient
// Run with:
// export DOTNET_TieredCompilation=0
// dotnet run -c Release
using System.Buffers;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkRunner.Run<Benchmarks>(args: args);
[MediumRunJob]
public class Benchmarks
{
// From https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs#L126
const int DefaultCopyBufferSize = 81920;
// 478MB file
const string URL = "http://10.5.2.105/videos/Shows/Channel%209/RB_XNA_Launch.wmv";
const string DEST = "/tmp/RB_XNA_Launch.wmv";
static HttpClient client = new HttpClient();
[Benchmark(Baseline = true)]
public async Task CopyToAsync()
{
using var httpStream = await client.GetStreamAsync(URL);
using var fileStream = File.Create(DEST);
await httpStream.CopyToAsync(fileStream, DefaultCopyBufferSize);
}
[Benchmark]
[Arguments(0, 0)]
[Arguments(2, 1)]
[Arguments(5, 1)]
[Arguments(10, 1)]
public async Task CopyWithDelay(int delayEvery, int delay)
{
using var httpStream = await client.GetStreamAsync(URL);
using var fileStream = File.Create(DEST);
byte[] buffer = ArrayPool<byte>.Shared.Rent(DefaultCopyBufferSize);
try
{
long iterations = 0;
int bytesRead;
while ((bytesRead = await httpStream.ReadAsync(new Memory<byte>(buffer))) != 0)
{
await fileStream.WriteAsync(new ReadOnlyMemory<byte>(buffer, 0, bytesRead));
if (++iterations == delayEvery)
{
Thread.Sleep(delay);
iterations = 0;
}
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
}
BenchmarkDotNet v0.14.0, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
AMD Ryzen Threadripper PRO 3955WX 16-Cores, 1 CPU, 32 logical and 16 physical cores
1Gbps network connection to remote server

.NET SDK 8.0.401
  [Host]    : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2
  MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2

Job=MediumRun  IterationCount=15  LaunchCount=2  
WarmupCount=10  
DOTNET_TieredCompilation=0
Method delayEvery delay Mean Error StdDev
CopyToAsync ? ? 5.322 s 0.2452 s 0.3437 s
CopyWithDelay 0 0 5.369 s 0.1769 s 0.2593 s
CopyWithDelay 2 1 5.374 s 0.1189 s 0.1780 s
CopyWithDelay 5 1 5.364 s 0.1672 s 0.2451 s
CopyWithDelay 10 1 5.368 s 0.1187 s 0.1740 s
CopyWithDelay 10 10 10.735 s 3.1946 s 4.6826 s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment