Checkin for caching the template matching for significant route finder performance improvements (#728)

This commit is contained in:
Phil Proctor
2018-12-26 15:05:20 -05:00
committed by Marcelo Castagna
parent ac211886f1
commit 9bbb6364f2
7 changed files with 124 additions and 114 deletions

View File

@ -1,51 +1,52 @@
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Validators;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
namespace Ocelot.Benchmarks
{
[Config(typeof(UrlPathToUrlPathTemplateMatcherBenchmarks))]
public class UrlPathToUrlPathTemplateMatcherBenchmarks : ManualConfig
{
private RegExUrlMatcher _urlPathMatcher;
private string _downstreamUrlPath;
private string _downstreamUrlPathTemplate;
private string _upstreamQuery;
public UrlPathToUrlPathTemplateMatcherBenchmarks()
{
Add(StatisticColumn.AllStatistics);
Add(MemoryDiagnoser.Default);
Add(BaselineValidator.FailOnError);
}
[GlobalSetup]
public void SetUp()
{
_urlPathMatcher = new RegExUrlMatcher();
_downstreamUrlPath = "api/product/products/1/variants/?soldout=false";
_downstreamUrlPathTemplate = "api/product/products/{productId}/variants/";
}
[Benchmark(Baseline = true)]
public void Baseline()
{
_urlPathMatcher.Match(_downstreamUrlPath, _upstreamQuery, _downstreamUrlPathTemplate, false);
}
// * Summary *
// BenchmarkDotNet=v0.10.13, OS=macOS 10.12.6 (16G1212) [Darwin 16.7.0]
// Intel Core i5-4278U CPU 2.60GHz (Haswell), 1 CPU, 4 logical cores and 2 physical cores
// .NET Core SDK=2.1.4
// [Host] : .NET Core 2.0.6 (CoreCLR 4.6.0.0, CoreFX 4.6.26212.01), 64bit RyuJIT
// DefaultJob : .NET Core 2.0.6 (CoreCLR 4.6.0.0, CoreFX 4.6.26212.01), 64bit RyuJIT
// Method | Mean | Error | StdDev | StdErr | Min | Q1 | Median | Q3 | Max | Op/s |
// ----------- |---------:|----------:|----------:|----------:|---------:|---------:|---------:|---------:|---------:|----------:|
// Benchmark1 | 3.133 us | 0.0492 us | 0.0460 us | 0.0119 us | 3.082 us | 3.100 us | 3.122 us | 3.168 us | 3.233 us | 319,161.9 |
}
}
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Validators;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Values;
namespace Ocelot.Benchmarks
{
[Config(typeof(UrlPathToUrlPathTemplateMatcherBenchmarks))]
public class UrlPathToUrlPathTemplateMatcherBenchmarks : ManualConfig
{
private RegExUrlMatcher _urlPathMatcher;
private UpstreamPathTemplate _pathTemplate;
private string _downstreamUrlPath;
private string _upstreamQuery;
public UrlPathToUrlPathTemplateMatcherBenchmarks()
{
Add(StatisticColumn.AllStatistics);
Add(MemoryDiagnoser.Default);
Add(BaselineValidator.FailOnError);
}
[GlobalSetup]
public void SetUp()
{
_urlPathMatcher = new RegExUrlMatcher();
_pathTemplate = new UpstreamPathTemplate("api/product/products/{productId}/variants/", 0, false, null);
_downstreamUrlPath = "api/product/products/1/variants/?soldout=false";
}
[Benchmark(Baseline = true)]
public void Baseline()
{
_urlPathMatcher.Match(_downstreamUrlPath, _upstreamQuery, _pathTemplate);
}
// * Summary *
// BenchmarkDotNet=v0.10.13, OS=macOS 10.12.6 (16G1212) [Darwin 16.7.0]
// Intel Core i5-4278U CPU 2.60GHz (Haswell), 1 CPU, 4 logical cores and 2 physical cores
// .NET Core SDK=2.1.4
// [Host] : .NET Core 2.0.6 (CoreCLR 4.6.0.0, CoreFX 4.6.26212.01), 64bit RyuJIT
// DefaultJob : .NET Core 2.0.6 (CoreCLR 4.6.0.0, CoreFX 4.6.26212.01), 64bit RyuJIT
// Method | Mean | Error | StdDev | StdErr | Min | Q1 | Median | Q3 | Max | Op/s |
// ----------- |---------:|----------:|----------:|----------:|---------:|---------:|---------:|---------:|---------:|----------:|
// Benchmark1 | 3.133 us | 0.0492 us | 0.0460 us | 0.0119 us | 3.082 us | 3.100 us | 3.122 us | 3.168 us | 3.233 us | 319,161.9 |
}
}

View File

@ -624,7 +624,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
.When(x => x.WhenICallTheFinder())
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(1))
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(1, 0))
.BDDfy();
}
@ -677,7 +677,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamPathTemplate(new UpstreamPathTemplate("someUpstreamPath", 1, false, "test"))
.Build()
)))
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(2))
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(1, 0))
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(1, 1))
.BDDfy();
}
@ -706,32 +707,32 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
private void ThenTheUrlMatcherIsCalledCorrectly()
{
_mockMatcher
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern.Template, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Once);
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern), Times.Once);
}
private void ThenTheUrlMatcherIsCalledCorrectly(int times)
private void ThenTheUrlMatcherIsCalledCorrectly(int times, int index = 0)
{
_mockMatcher
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern.OriginalValue, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Exactly(times));
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[index].UpstreamTemplatePattern), Times.Exactly(times));
}
private void ThenTheUrlMatcherIsCalledCorrectly(string expectedUpstreamUrlPath)
{
_mockMatcher
.Verify(x => x.Match(expectedUpstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern.OriginalValue, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Once);
.Verify(x => x.Match(expectedUpstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern), Times.Once);
}
private void ThenTheUrlMatcherIsNotCalled()
{
_mockMatcher
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern.OriginalValue, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Never);
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamTemplatePattern), Times.Never);
}
private void GivenTheUrlMatcherReturns(Response<UrlMatch> match)
{
_match = match;
_mockMatcher
.Setup(x => x.Match(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Setup(x => x.Match(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<UpstreamPathTemplate>()))
.Returns(_match);
}

View File

@ -1,5 +1,6 @@
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Responses;
using Ocelot.Values;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
@ -270,7 +271,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
private void WhenIMatchThePaths()
{
_result = _urlMatcher.Match(_path, _queryString, _downstreamPathTemplate, _containsQueryString);
_result = _urlMatcher.Match(_path, _queryString, new UpstreamPathTemplate(_downstreamPathTemplate, 0, _containsQueryString, _downstreamPathTemplate));
}
private void ThenTheResultIsTrue()