diff --git a/.gitignore b/.gitignore
index 5f8dfa9f48..d3ebe6b4bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ packages/
artifacts/
PublishProfiles/
.vs/
+.vscode/
.build/
.testPublish/
bower_components/
diff --git a/Routing.sln b/Routing.sln
index 13657187fa..e1478b7f15 100644
--- a/Routing.sln
+++ b/Routing.sln
@@ -45,6 +45,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Routin
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{D5F39F59-5725-4127-82E7-67028D006185}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarkapps", "benchmarkapps", "{7F5914E2-C63F-4759-898E-462804357C90}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "benchmarkapps\Benchmarks\Benchmarks.csproj", "{91F47A60-9A78-4968-B10D-157D9BFAC37F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -145,6 +149,18 @@ Global
{F3D86714-4E64-41A6-9B36-A47B3683CF5D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{F3D86714-4E64-41A6-9B36-A47B3683CF5D}.Release|x86.ActiveCfg = Release|Any CPU
{F3D86714-4E64-41A6-9B36-A47B3683CF5D}.Release|x86.Build.0 = Release|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Debug|x86.Build.0 = Debug|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Release|x86.ActiveCfg = Release|Any CPU
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -158,6 +174,7 @@ Global
{741B0B05-CE96-473B-B962-6B0A347DF79A} = {95359B4B-4C85-4B44-A75B-0621905C4CF6}
{5C73140B-41F3-466F-A07B-3614E4D80DF9} = {95359B4B-4C85-4B44-A75B-0621905C4CF6}
{F3D86714-4E64-41A6-9B36-A47B3683CF5D} = {D5F39F59-5725-4127-82E7-67028D006185}
+ {91F47A60-9A78-4968-B10D-157D9BFAC37F} = {7F5914E2-C63F-4759-898E-462804357C90}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {36C8D815-B7F1-479D-894B-E606FB8DECDA}
diff --git a/benchmarkapps/Benchmarks/Benchmarks.csproj b/benchmarkapps/Benchmarks/Benchmarks.csproj
new file mode 100644
index 0000000000..3a791502b2
--- /dev/null
+++ b/benchmarkapps/Benchmarks/Benchmarks.csproj
@@ -0,0 +1,19 @@
+
+
+
+ netcoreapp2.2
+ $(BenchmarksTargetFramework)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/benchmarkapps/Benchmarks/Program.cs b/benchmarkapps/Benchmarks/Program.cs
new file mode 100644
index 0000000000..5545205d13
--- /dev/null
+++ b/benchmarkapps/Benchmarks/Program.cs
@@ -0,0 +1,30 @@
+// 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 Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+
+namespace Benchmarks
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ GetWebHostBuilder(args).Build().Run();
+ }
+
+ public static IWebHostBuilder GetWebHostBuilder(string[] args)
+ {
+ var config = new ConfigurationBuilder()
+ .Build();
+
+ // Consoler logger has a major impact on perf results, so do not use
+ // default builder.
+
+ return new WebHostBuilder()
+ .UseConfiguration(config)
+ .UseKestrel()
+ .UseStartup();
+ }
+ }
+}
diff --git a/benchmarkapps/Benchmarks/Startup.cs b/benchmarkapps/Benchmarks/Startup.cs
new file mode 100644
index 0000000000..e8c51cbaeb
--- /dev/null
+++ b/benchmarkapps/Benchmarks/Startup.cs
@@ -0,0 +1,36 @@
+// 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 Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.DependencyInjection;
+using System.Text;
+
+namespace Benchmarks
+{
+ public class Startup
+ {
+ private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!");
+
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddRouting();
+ }
+
+ public void Configure(IApplicationBuilder app)
+ {
+ app.UseRouter(routes =>
+ {
+ routes.MapRoute("/plaintext", (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);
+ });
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/benchmarkapps/Benchmarks/benchmarks.json b/benchmarkapps/Benchmarks/benchmarks.json
new file mode 100644
index 0000000000..2ad0282994
--- /dev/null
+++ b/benchmarkapps/Benchmarks/benchmarks.json
@@ -0,0 +1,19 @@
+{
+ "Default": {
+ "Client": "Wrk",
+ "PresetHeaders": "Plaintext",
+ "ClientProperties": {
+ "ScriptName": "pipeline",
+ "PipelineDepth": 16
+ },
+ "Source": {
+ "Repository": "https://github.com/aspnet/routing.git",
+ "BranchOrCommit": "dev",
+ "Project": "benchmarkapps/Benchmarks/Benchmarks.csproj"
+ },
+ "Port": 8080
+ },
+ "Plaintext": {
+ "Path": "/plaintext"
+ }
+}
diff --git a/build/dependencies.props b/build/dependencies.props
index 85f806f47e..2d9d8d4e41 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -5,6 +5,7 @@
0.10.13
2.2.0-preview1-17064
+ 2.2.0-preview1-34326
2.2.0-preview1-34326
2.2.0-preview1-34326
2.2.0-preview1-34326
@@ -14,6 +15,7 @@
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/BenchmarksTest.cs b/test/Microsoft.AspNetCore.Routing.FunctionalTests/BenchmarksTest.cs
new file mode 100644
index 0000000000..30b8411b9c
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/BenchmarksTest.cs
@@ -0,0 +1,53 @@
+// 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 BenchmarksTest : IDisposable
+ {
+ private readonly HttpClient _client;
+ private readonly TestServer _testServer;
+
+ public BenchmarksTest()
+ {
+ var webHostBuilder = Benchmarks.Program.GetWebHostBuilder(args: null);
+ _testServer = new TestServer(webHostBuilder);
+ _client = _testServer.CreateClient();
+ _client.BaseAddress = new Uri("http://localhost");
+ }
+
+ [Fact]
+ public async Task RouteHandlerWritesResponse()
+ {
+ // 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/Microsoft.AspNetCore.Routing.FunctionalTests.csproj b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj
index ee8a57c08f..9520c32ff5 100644
--- a/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj
+++ b/test/Microsoft.AspNetCore.Routing.FunctionalTests/Microsoft.AspNetCore.Routing.FunctionalTests.csproj
@@ -1,4 +1,4 @@
-
+
$(StandardTestTfms)
@@ -9,6 +9,10 @@
+
+
+
+