diff --git a/benchmarkapps/Benchmarks/Benchmarks.csproj b/benchmarkapps/Benchmarks/Benchmarks.csproj index 3a791502b2..b85c439bc7 100644 --- a/benchmarkapps/Benchmarks/Benchmarks.csproj +++ b/benchmarkapps/Benchmarks/Benchmarks.csproj @@ -5,13 +5,15 @@ $(BenchmarksTargetFramework) - + + + - + diff --git a/benchmarkapps/Benchmarks/Program.cs b/benchmarkapps/Benchmarks/Program.cs index 5545205d13..a37a131d9c 100644 --- a/benchmarkapps/Benchmarks/Program.cs +++ b/benchmarkapps/Benchmarks/Program.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -16,15 +17,37 @@ namespace Benchmarks public static IWebHostBuilder GetWebHostBuilder(string[] args) { var config = new ConfigurationBuilder() + .AddCommandLine(args) + .AddEnvironmentVariables(prefix: "RoutingBenchmarks_") .Build(); // Consoler logger has a major impact on perf results, so do not use // default builder. - return new WebHostBuilder() - .UseConfiguration(config) - .UseKestrel() - .UseStartup(); + var webHostBuilder = new WebHostBuilder() + .UseConfiguration(config) + .UseKestrel(); + + var scenario = config["scenarios"]?.ToLower(); + if (scenario == "plaintextdispatcher") + { + webHostBuilder.UseStartup(); + // for testing + webHostBuilder.UseSetting("Startup", nameof(StartupUsingDispatcher)); + } + else if (scenario == "plaintextrouting") + { + webHostBuilder.UseStartup(); + // for testing + webHostBuilder.UseSetting("Startup", nameof(StartupUsingRouting)); + } + else + { + throw new InvalidOperationException( + $"Invalid scenario '{scenario}'. Allowed scenarios are PlaintextDispatcher and PlaintextRouting"); + } + + return webHostBuilder; } } } diff --git a/benchmarkapps/Benchmarks/StartupUsingDispatcher.cs b/benchmarkapps/Benchmarks/StartupUsingDispatcher.cs new file mode 100644 index 0000000000..bfd6069eca --- /dev/null +++ b/benchmarkapps/Benchmarks/StartupUsingDispatcher.cs @@ -0,0 +1,50 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Text; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Routing.Matchers; +using Microsoft.Extensions.DependencyInjection; + +namespace Benchmarks +{ + public class StartupUsingDispatcher + { + private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!"); + + public void ConfigureServices(IServiceCollection services) + { + services.AddRouting(); + + services.AddDispatcher(options => + { + options.DataSources.Add(new DefaultEndpointDataSource(new[] + { + new MatcherEndpoint( + invoker: (next) => (httpContext) => + { + var response = httpContext.Response; + var payloadLength = _helloWorldPayload.Length; + response.StatusCode = 200; + response.ContentType = "text/plain"; + response.ContentLength = payloadLength; + return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength); + }, + template: "/plaintext", + values: new { }, + order: 0, + metadata: EndpointMetadataCollection.Empty, + displayName: "Plaintext"), + })); + }); + } + + public void Configure(IApplicationBuilder app) + { + app.UseDispatcher(); + + app.UseEndpoint(); + } + } +} \ No newline at end of file diff --git a/benchmarkapps/Benchmarks/Startup.cs b/benchmarkapps/Benchmarks/StartupUsingRouting.cs similarity index 96% rename from benchmarkapps/Benchmarks/Startup.cs rename to benchmarkapps/Benchmarks/StartupUsingRouting.cs index e8c51cbaeb..d9e2999af3 100644 --- a/benchmarkapps/Benchmarks/Startup.cs +++ b/benchmarkapps/Benchmarks/StartupUsingRouting.cs @@ -8,7 +8,7 @@ using System.Text; namespace Benchmarks { - public class Startup + public class StartupUsingRouting { private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!"); diff --git a/benchmarkapps/Benchmarks/benchmarks.json b/benchmarkapps/Benchmarks/benchmarks.json index edb513e2dd..59cfd09eb7 100644 --- a/benchmarkapps/Benchmarks/benchmarks.json +++ b/benchmarkapps/Benchmarks/benchmarks.json @@ -15,5 +15,8 @@ }, "PlaintextRouting": { "Path": "/plaintext" + }, + "PlaintextDispatcher": { + "Path": "/plaintext" } -} +} \ No newline at end of file diff --git a/build/dependencies.props b/build/dependencies.props index bb2e38a84e..c615caa103 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -17,6 +17,8 @@ 2.2.0-preview1-34326 2.2.0-preview1-34326 2.2.0-preview1-34326 + 2.2.0-preview1-34326 + 2.2.0-preview1-34326 2.2.0-preview1-34326 2.2.0-preview1-34326 2.2.0-preview1-34326 diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/DispatcherTest.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/DispatcherTest.cs new file mode 100644 index 0000000000..3b963b56a5 --- /dev/null +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/DispatcherTest.cs @@ -0,0 +1,60 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#if NETCOREAPP2_2 +using System; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.TestHost; +using Xunit; + +namespace Microsoft.AspNetCore.Routing.FunctionalTests +{ + public class DispatcherTest : IDisposable + { + private readonly HttpClient _client; + private readonly TestServer _testServer; + + public DispatcherTest() + { + // This switch and value are set by benchmark server when running the app for profiling. + var args = new[] { "--scenarios", "PlaintextDispatcher" }; + var webHostBuilder = Benchmarks.Program.GetWebHostBuilder(args); + + // Make sure we are using the right startup + var startupName = webHostBuilder.GetSetting("Startup"); + Assert.Equal(nameof(Benchmarks.StartupUsingDispatcher), startupName); + + _testServer = new TestServer(webHostBuilder); + _client = _testServer.CreateClient(); + _client.BaseAddress = new Uri("http://localhost"); + } + + [Fact] + public async Task RouteEndpoint_ReturnsPlaintextResponse() + { + // Arrange + var expectedContentType = "text/plain"; + var expectedContent = "Hello, World!"; + + // Act + var response = await _client.GetAsync("/plaintext"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + Assert.NotNull(response.Content.Headers.ContentType); + Assert.Equal(expectedContentType, response.Content.Headers.ContentType.MediaType); + var actualContent = await response.Content.ReadAsStringAsync(); + Assert.Equal(expectedContent, actualContent); + } + + public void Dispose() + { + _testServer.Dispose(); + _client.Dispose(); + } + } +} +#endif \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Routing.FunctionalTests/BenchmarksTest.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/RoutingTest.cs similarity index 77% rename from test/Microsoft.AspNetCore.Routing.FunctionalTests/BenchmarksTest.cs rename to test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/RoutingTest.cs index 30b8411b9c..ae4ef90f06 100644 --- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/BenchmarksTest.cs +++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Benchmarks/RoutingTest.cs @@ -11,14 +11,21 @@ using Xunit; namespace Microsoft.AspNetCore.Routing.FunctionalTests { - public class BenchmarksTest : IDisposable + public class RoutingTest : IDisposable { private readonly HttpClient _client; private readonly TestServer _testServer; - public BenchmarksTest() + public RoutingTest() { - var webHostBuilder = Benchmarks.Program.GetWebHostBuilder(args: null); + // This switch and value are set by benchmark server when running the app for profiling. + var args = new[] { "--scenarios", "PlaintextRouting" }; + var webHostBuilder = Benchmarks.Program.GetWebHostBuilder(args); + + // Make sure we are using the right startup + var startupName = webHostBuilder.GetSetting("Startup"); + Assert.Equal(nameof(Benchmarks.StartupUsingRouting), startupName); + _testServer = new TestServer(webHostBuilder); _client = _testServer.CreateClient(); _client.BaseAddress = new Uri("http://localhost");