diff --git a/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/Benchmark.cs b/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HedgingBenchmark.cs similarity index 90% rename from bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/Benchmark.cs rename to bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HedgingBenchmark.cs index fb565f14cbe..f0f85fe4421 100644 --- a/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/Benchmark.cs +++ b/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HedgingBenchmark.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Net.Http; using System.Threading; using System.Threading.Tasks; @@ -9,11 +10,12 @@ namespace Microsoft.Extensions.Http.Resilience.Bench; -public class Benchmark +public class HedgingBenchmark { - private static HttpRequestMessage Request => new(HttpMethod.Post, "https://bogus"); + private static readonly Uri _uri = new("https://bogus"); + private static HttpRequestMessage Request => new(HttpMethod.Post, _uri); - private System.Net.Http.HttpClient _client = null!; + private HttpClient _client = null!; [GlobalSetup] public void GlobalSetup() diff --git a/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HttpClientFactory.cs b/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HttpClientFactory.cs index 6d36543189a..43bae55a908 100644 --- a/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HttpClientFactory.cs +++ b/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HttpClientFactory.cs @@ -4,9 +4,13 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Threading; using Microsoft.Extensions.Compliance.Redaction; using Microsoft.Extensions.Compliance.Testing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Telemetry.Metering; #pragma warning disable R9A033 // Replace uses of 'Enum.GetName' and 'Enum.ToString' with the '[EnumStrings]' code generator for improved performance @@ -24,6 +28,10 @@ public enum HedgingClientType internal static class HttpClientFactory { + internal const string EmptyClient = "Empty"; + + internal const string StandardClient = "Standard"; + private const string HedgingEndpoint1 = "http://localhost1"; private const string HedgingEndpoint2 = "http://localhost2"; @@ -34,14 +42,25 @@ public static ServiceProvider InitializeServiceProvider(HedgingClientType client .RegisterMetering() .AddSingleton(NullRedactorProvider.Instance) .AddTransient() - .AddHedging(clientType); + .AddHedging(clientType) + .AddHttpClient(StandardClient, client => client.Timeout = Timeout.InfiniteTimeSpan) + .AddStandardResilienceHandler() + .Services + .AddHttpClient(StandardClient) + .AddHttpMessageHandler() + .Services + .AddHttpClient(EmptyClient, client => client.Timeout = Timeout.InfiniteTimeSpan) + .AddHttpMessageHandler(); + + services.RemoveAll(); + services.AddSingleton(NullLoggerFactory.Instance); return services.BuildServiceProvider(); } private static IServiceCollection AddHedging(this IServiceCollection services, HedgingClientType clientType) { - var clientBuilder = services.AddHttpClient(clientType.ToString()); + var clientBuilder = services.AddHttpClient(clientType.ToString(), client => client.Timeout = Timeout.InfiniteTimeSpan); var hedgingBuilder = clientBuilder.AddStandardHedgingHandler().SelectPipelineByAuthority(SimpleClassifications.PublicData); _ = clientBuilder.AddHttpMessageHandler(); diff --git a/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HttpResilienceBenchmark.cs b/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HttpResilienceBenchmark.cs new file mode 100644 index 00000000000..6f719b3cc8e --- /dev/null +++ b/bench/Libraries/Microsoft.Extensions.Http.Resilience.PerformanceTests/HttpResilienceBenchmark.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Extensions.Http.Resilience.Bench; + +public class HttpResilienceBenchmark +{ + private static readonly Uri _uri = new("https://bogus"); + + private HttpClient _client = null!; + private HttpClient _standardClient = null!; + private HttpClient _hedgingClient = null!; + + private static HttpRequestMessage Request + { + get + { + var request = new HttpRequestMessage(HttpMethod.Post, _uri); + request.Options.Set(new HttpRequestOptionsKey("dummy"), "dummy"); + return request; + } + } + + [GlobalSetup] + public void GlobalSetup() + { + var serviceProvider = HttpClientFactory.InitializeServiceProvider(HedgingClientType.Ordered); + var factory = serviceProvider.GetRequiredService(); + _client = factory.CreateClient(HttpClientFactory.EmptyClient); + _standardClient = factory.CreateClient(HttpClientFactory.StandardClient); + _hedgingClient = factory.CreateClient(nameof(HedgingClientType.Ordered)); + } + + [Benchmark(Baseline = true)] + public Task DefaultClient() + { + return _client.SendAsync(Request, CancellationToken.None); + } + + [Benchmark] + public Task StandardResilienceHandler() + { + return _standardClient.SendAsync(Request, CancellationToken.None); + } + + [Benchmark] + public Task StandardHedgingHandler() + { + return _hedgingClient.SendAsync(Request, CancellationToken.None); + } +}