aspnetcore/benchmarks/Microsoft.AspNetCore.Routin.../Matchers/MatcherBenchmarkBase.cs

93 lines
3.6 KiB
C#

// 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 System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.EndpointConstraints;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Routing.Matchers
{
public abstract class MatcherBenchmarkBase
{
private protected MatcherEndpoint[] Endpoints;
private protected HttpContext[] Requests;
// The older routing implementations retrieve services when they first execute.
private protected static IServiceProvider CreateServices()
{
var services = new ServiceCollection();
services.AddLogging();
services.AddOptions();
services.AddRouting();
services.AddDispatcher();
return services.BuildServiceProvider();
}
private protected DfaMatcherBuilder CreateDfaMatcherBuilder()
{
var services = CreateServices();
return ActivatorUtilities.CreateInstance<DfaMatcherBuilder>(services);
}
private protected static MatcherEndpoint CreateEndpoint(string template, string httpMethod = null)
{
var metadata = new List<object>();
if (httpMethod != null)
{
metadata.Add(new HttpMethodEndpointConstraint(new string[] { httpMethod, }));
}
return new MatcherEndpoint(
(next) => (context) => Task.CompletedTask,
template,
new RouteValueDictionary(),
new RouteValueDictionary(),
new List<MatchProcessorReference>(),
0,
new EndpointMetadataCollection(metadata),
template);
}
private protected static int[] SampleRequests(int endpointCount, int count)
{
// This isn't very high tech, but it's at least regular distribution.
// We sort the route templates by precedence, so this should result in
// an even distribution of the 'complexity' of the routes that are exercised.
var frequency = endpointCount / count;
if (frequency < 2)
{
throw new InvalidOperationException(
"The sample count is too high. This won't produce an accurate sampling" +
"of the request data.");
}
var samples = new int[count];
for (var i = 0; i < samples.Length; i++)
{
samples[i] = i * frequency;
}
return samples;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private protected void Validate(HttpContext httpContext, Endpoint expected, Endpoint actual)
{
if (!object.ReferenceEquals(expected, actual))
{
var message = new StringBuilder();
message.AppendLine($"Validation failed for request {Array.IndexOf(Requests, httpContext)}");
message.AppendLine($"{httpContext.Request.Method} {httpContext.Request.Path}");
message.AppendLine($"expected: '{((MatcherEndpoint)expected)?.DisplayName ?? "null"}'");
message.AppendLine($"actual: '{((MatcherEndpoint)actual)?.DisplayName ?? "null"}'");
throw new InvalidOperationException(message.ToString());
}
}
}
}