From 18bdf25fccdc6e49244a3d4682fa332957b00846 Mon Sep 17 00:00:00 2001 From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com> Date: Wed, 25 Mar 2026 19:31:44 +0100 Subject: [PATCH 1/2] feat: Add Benchmarks --- Docker.DotNet.slnx | 5 +- .../Docker.DotNet.Benchmarks.csproj | 44 +++++++ .../DockerDaemonRoundtripBenchmarks.cs | 112 ++++++++++++++++++ test/Docker.DotNet.Benchmarks/Program.cs | 2 + test/Docker.DotNet.Benchmarks/README.md | 23 ++++ 5 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj create mode 100644 test/Docker.DotNet.Benchmarks/DockerDaemonRoundtripBenchmarks.cs create mode 100644 test/Docker.DotNet.Benchmarks/Program.cs create mode 100644 test/Docker.DotNet.Benchmarks/README.md diff --git a/Docker.DotNet.slnx b/Docker.DotNet.slnx index dce2229d..2da18906 100644 --- a/Docker.DotNet.slnx +++ b/Docker.DotNet.slnx @@ -6,6 +6,8 @@ + + @@ -15,10 +17,9 @@ - - + diff --git a/test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj b/test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj new file mode 100644 index 00000000..1764025c --- /dev/null +++ b/test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj @@ -0,0 +1,44 @@ + + + net10.0 + Exe + false + false + + + 3.132.0 + false + + + + + + + + $(DefineConstants);DOCKER_DOTNET_RELEASE + + + + + + + + $(DefineConstants);DOCKER_DOTNET_MAIN + + + + + + + + + + + + + + + + + + diff --git a/test/Docker.DotNet.Benchmarks/DockerDaemonRoundtripBenchmarks.cs b/test/Docker.DotNet.Benchmarks/DockerDaemonRoundtripBenchmarks.cs new file mode 100644 index 00000000..75764279 --- /dev/null +++ b/test/Docker.DotNet.Benchmarks/DockerDaemonRoundtripBenchmarks.cs @@ -0,0 +1,112 @@ +namespace Docker.DotNet.Benchmarks; + +[MemoryDiagnoser] +public class DockerDaemonRoundtripBenchmarks +{ + private readonly string _imageReference = "busybox:1.37"; + + private DockerClient _client = null!; + + [GlobalSetup] + public async Task GlobalSetup() + { +#if DOCKER_DOTNET_RELEASE + const string implementation = "release"; +#else + const string implementation = "main"; +#endif + + var builder = new DockerClientBuilder(); + + _client = builder.Build(); + + Console.WriteLine($"Running daemon round-trip benchmarks against: {implementation}"); + + await _client.System.PingAsync(CancellationToken.None) + .ConfigureAwait(false); + + await EnsureImageExistsAsync() + .ConfigureAwait(false); + } + + [GlobalCleanup] + public void GlobalCleanup() + { + _client.Dispose(); + } + + [Benchmark] + public async Task CreateContainerRequestResponse() + { + var parameters = new CreateContainerParameters(); + parameters.Name = $"dockerdotnet-benchmark-{Guid.NewGuid():N}"; + parameters.Image = _imageReference; + parameters.Cmd = ["sh", "-c", "sleep 1"]; + parameters.Labels = new Dictionary(); + parameters.Labels.Add("suite", "benchmark"); + parameters.Labels.Add("scenario", "create-roundtrip"); + + var response = await _client.Containers.CreateContainerAsync(parameters, CancellationToken.None) + .ConfigureAwait(false); + + try + { + return response.ID.Length; + } + finally + { + await SafeRemoveContainerAsync(response.ID) + .ConfigureAwait(false); + } + } + + [Benchmark] + public async Task StartContainerRequestResponse() + { + var parameters = new CreateContainerParameters(); + parameters.Name = $"dockerdotnet-benchmark-{Guid.NewGuid():N}"; + parameters.Image = _imageReference; + parameters.Cmd = ["sh", "-c", "exit 0"]; + parameters.Labels = new Dictionary(); + parameters.Labels.Add("suite", "benchmark"); + parameters.Labels.Add("scenario", "start-roundtrip"); + + var response = await _client.Containers.CreateContainerAsync(parameters, CancellationToken.None) + .ConfigureAwait(false); + + try + { + return await _client.Containers.StartContainerAsync(response.ID, new ContainerStartParameters(), CancellationToken.None) + .ConfigureAwait(false); + } + finally + { + await SafeRemoveContainerAsync(response.ID) + .ConfigureAwait(false); + } + } + + private async Task EnsureImageExistsAsync() + { + var parameters = new ImagesCreateParameters(); + parameters.FromImage = _imageReference; + + await _client.Images.CreateImageAsync(parameters, new AuthConfig(), new Progress(_ => { }), CancellationToken.None) + .ConfigureAwait(false); + } + + private async Task SafeRemoveContainerAsync(string containerId) + { + var parameters = new ContainerRemoveParameters(); + parameters.Force = true; + + try + { + await _client.Containers.RemoveContainerAsync(containerId, parameters, CancellationToken.None) + .ConfigureAwait(false); + } + catch (DockerContainerNotFoundException) + { + } + } +} \ No newline at end of file diff --git a/test/Docker.DotNet.Benchmarks/Program.cs b/test/Docker.DotNet.Benchmarks/Program.cs new file mode 100644 index 00000000..10434bbc --- /dev/null +++ b/test/Docker.DotNet.Benchmarks/Program.cs @@ -0,0 +1,2 @@ +Type[] benchmarks = [typeof(DockerDaemonRoundtripBenchmarks)]; +BenchmarkSwitcher.FromTypes(benchmarks).Run(args); \ No newline at end of file diff --git a/test/Docker.DotNet.Benchmarks/README.md b/test/Docker.DotNet.Benchmarks/README.md new file mode 100644 index 00000000..180bb425 --- /dev/null +++ b/test/Docker.DotNet.Benchmarks/README.md @@ -0,0 +1,23 @@ +# Docker.DotNet Benchmarks + +This benchmark project compares the current `main` source code against a released NuGet package by running the same benchmark class twice. + +## Run + +From the repository root, run `main` first: + +```bash +dotnet run -c Release --project test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj -- --filter '*DockerDaemonRoundtripBenchmarks*' +``` + +Then run the released NuGet package implementation: + +```bash +dotnet run -c Release --project test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj -p:UseReleasedPackage=true -- --filter '*DockerDaemonRoundtripBenchmarks*' +``` + +To compare against a different release tag/package version: + +```bash +dotnet run -c Release --project test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj -p:UseReleasedPackage=true -p:DockerDotNetReleaseVersion=3.132.0 -- --filter '*DockerDaemonRoundtripBenchmarks*' +``` From 3924426638b222eb4a22ccd65379a362612e5e14 Mon Sep 17 00:00:00 2001 From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com> Date: Sat, 28 Mar 2026 09:10:20 +0100 Subject: [PATCH 2/2] fix: Add TFM net8.0 and net9.0 --- test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj b/test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj index 1764025c..3a14b63c 100644 --- a/test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj +++ b/test/Docker.DotNet.Benchmarks/Docker.DotNet.Benchmarks.csproj @@ -1,6 +1,6 @@ - net10.0 + net8.0;net9.0;net10.0 Exe false false