Improve HeaderSplit perf (#9309)

This commit is contained in:
BrennanConroy 2019-04-11 22:29:23 -07:00 committed by GitHub
parent 6aee83d8f0
commit 022e79cf17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 5 deletions

View File

@ -19,11 +19,9 @@ namespace Microsoft.AspNetCore.Http.Internal
public static StringValues GetHeaderSplit(IHeaderDictionary headers, string key)
{
var values = GetHeaderUnmodified(headers, key);
return new StringValues(GetHeaderSplitImplementation(values).ToArray());
}
private static IEnumerable<string> GetHeaderSplitImplementation(StringValues values)
{
StringValues result = default;
foreach (var segment in new HeaderSegmentCollection(values))
{
if (!StringSegment.IsNullOrEmpty(segment.Data))
@ -31,10 +29,12 @@ namespace Microsoft.AspNetCore.Http.Internal
var value = DeQuote(segment.Data.Value);
if (!string.IsNullOrEmpty(value))
{
yield return value;
result = StringValues.Concat(in result, value);
}
}
}
return result;
}
public static StringValues GetHeaderUnmodified(IHeaderDictionary headers, string key)

View File

@ -0,0 +1 @@
[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark]

View File

@ -0,0 +1,63 @@
// 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 BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Http.Abstractions.Microbenchmarks
{
public class GetHeaderSplitBenchmark
{
HeaderDictionary _dictionary;
[GlobalSetup]
public void GlobalSetup()
{
var dict = new Dictionary<string, StringValues>()
{
{ "singleValue", new StringValues("single") },
{ "singleValueQuoted", new StringValues("\"single\"") },
{ "doubleValue", new StringValues(new [] { "first", "second" }) },
{ "manyValue", new StringValues(new [] { "first", "second", "third", "fourth", "fifth", "sixth" }) }
};
_dictionary = new HeaderDictionary(dict);
}
[Benchmark]
public void SplitSingleHeader()
{
var values = ParsingHelpers.GetHeaderSplit(_dictionary, "singleValue");
if (values.Count != 1)
throw new Exception();
}
[Benchmark]
public void SplitSingleQuotedHeader()
{
var values = ParsingHelpers.GetHeaderSplit(_dictionary, "singleValueQuoted");
if (values.Count != 1)
throw new Exception();
}
[Benchmark]
public void SplitDoubleHeader()
{
var values = ParsingHelpers.GetHeaderSplit(_dictionary, "doubleValue");
if (values.Count != 2)
throw new Exception();
}
[Benchmark]
public void SplitManyHeaders()
{
var values = ParsingHelpers.GetHeaderSplit(_dictionary, "manyValue");
if (values.Count != 6)
throw new Exception();
}
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="BenchmarkDotNet" />
<Reference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" />
<Reference Include="Microsoft.AspNetCore.Http.Abstractions" />
<Reference Include="Microsoft.AspNetCore.Http" />
</ItemGroup>
</Project>