aspnetcore/benchmarks/Kestrel.Performance/ResponseHeaderCollectionBen...

221 lines
9.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.Buffers;
using System.IO.Pipelines;
using System.Runtime.CompilerServices;
using System.Text;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{
public class ResponseHeaderCollectionBenchmark
{
private const int InnerLoopCount = 512;
private static readonly byte[] _bytesServer = Encoding.ASCII.GetBytes("\r\nServer: Kestrel");
private static readonly DateHeaderValueManager _dateHeaderValueManager = new DateHeaderValueManager();
private HttpResponseHeaders _responseHeadersDirect;
private HttpResponse _response;
public enum BenchmarkTypes
{
ContentLengthNumeric,
ContentLengthString,
Plaintext,
Common,
Unknown
}
[Params(
BenchmarkTypes.ContentLengthNumeric,
BenchmarkTypes.ContentLengthString,
BenchmarkTypes.Plaintext,
BenchmarkTypes.Common,
BenchmarkTypes.Unknown
)]
public BenchmarkTypes Type { get; set; }
[Benchmark(OperationsPerInvoke = InnerLoopCount)]
public void SetHeaders()
{
switch (Type)
{
case BenchmarkTypes.ContentLengthNumeric:
ContentLengthNumeric(InnerLoopCount);
break;
case BenchmarkTypes.ContentLengthString:
ContentLengthString(InnerLoopCount);
break;
case BenchmarkTypes.Plaintext:
Plaintext(InnerLoopCount);
break;
case BenchmarkTypes.Common:
Common(InnerLoopCount);
break;
case BenchmarkTypes.Unknown:
Unknown(InnerLoopCount);
break;
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void ContentLengthNumeric(int count)
{
for (var i = 0; i < count; i++)
{
_responseHeadersDirect.Reset();
_response.ContentLength = 0;
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void ContentLengthString(int count)
{
for (var i = 0; i < count; i++)
{
_responseHeadersDirect.Reset();
_response.Headers["Content-Length"] = "0";
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void Plaintext(int count)
{
for (var i = 0; i < count; i++)
{
_responseHeadersDirect.Reset();
_response.StatusCode = 200;
_response.ContentType = "text/plain";
_response.ContentLength = 13;
var dateHeaderValues = _dateHeaderValueManager.GetDateHeaderValues();
_responseHeadersDirect.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes);
_responseHeadersDirect.SetRawServer("Kestrel", _bytesServer);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void Common(int count)
{
for (var i = 0; i < count; i++)
{
_responseHeadersDirect.Reset();
_response.StatusCode = 200;
_response.ContentType = "text/css";
_response.ContentLength = 421;
var headers = _response.Headers;
headers["Connection"] = "Close";
headers["Cache-Control"] = "public, max-age=30672000";
headers["Vary"] = "Accept-Encoding";
headers["Content-Encoding"] = "gzip";
headers["Expires"] = "Fri, 12 Jan 2018 22:01:55 GMT";
headers["Last-Modified"] = "Wed, 22 Jun 2016 20:08:29 GMT";
headers["Set-Cookie"] = "prov=20629ccd-8b0f-e8ef-2935-cd26609fc0bc; __qca=P0-1591065732-1479167353442; _ga=GA1.2.1298898376.1479167354; _gat=1; sgt=id=9519gfde_3347_4762_8762_df51458c8ec2; acct=t=why-is-%e0%a5%a7%e0%a5%a8%e0%a5%a9-numeric&s=why-is-%e0%a5%a7%e0%a5%a8%e0%a5%a9-numeric";
headers["ETag"] = "\"54ef7954-1078\"";
headers["Transfer-Encoding"] = "chunked";
headers["Content-Language"] = "en-gb";
headers["Upgrade"] = "websocket";
headers["Via"] = "1.1 varnish";
headers["Access-Control-Allow-Origin"] = "*";
headers["Access-Control-Allow-credentials"] = "true";
headers["Access-Control-Expose-Headers"] = "Client-Protocol, Content-Length, Content-Type, X-Bandwidth-Est, X-Bandwidth-Est2, X-Bandwidth-Est-Comp, X-Bandwidth-Avg, X-Walltime-Ms, X-Sequence-Num";
var dateHeaderValues = _dateHeaderValueManager.GetDateHeaderValues();
_responseHeadersDirect.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes);
_responseHeadersDirect.SetRawServer("Kestrel", _bytesServer);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void Unknown(int count)
{
for (var i = 0; i < count; i++)
{
_responseHeadersDirect.Reset();
_response.StatusCode = 200;
_response.ContentType = "text/plain";
_response.ContentLength = 13;
var headers = _response.Headers;
headers["Link"] = "<https://www.gravatar.com/avatar/6ae816bfaad7bbc58b17fac49ef5cced?d=404&s=250>; rel=\"canonical\"";
headers["X-Ua-Compatible"] = "IE=Edge";
headers["X-Powered-By"] = "ASP.NET";
headers["X-Content-Type-Options"] = "nosniff";
headers["X-Xss-Protection"] = "1; mode=block";
headers["X-Frame-Options"] = "SAMEORIGIN";
headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload";
headers["Content-Security-Policy"] = "default-src 'none'; script-src 'self' cdnjs.cloudflare.com code.jquery.com scotthelme.disqus.com a.disquscdn.com www.google-analytics.com go.disqus.com platform.twitter.com cdn.syndication.twimg.com; style-src 'self' a.disquscdn.com fonts.googleapis.com cdnjs.cloudflare.com platform.twitter.com; img-src 'self' data: www.gravatar.com www.google-analytics.com links.services.disqus.com referrer.disqus.com a.disquscdn.com cdn.syndication.twimg.com syndication.twitter.com pbs.twimg.com platform.twitter.com abs.twimg.com; child-src fusiontables.googleusercontent.com fusiontables.google.com www.google.com disqus.com www.youtube.com syndication.twitter.com platform.twitter.com; frame-src fusiontables.googleusercontent.com fusiontables.google.com www.google.com disqus.com www.youtube.com syndication.twitter.com platform.twitter.com; connect-src 'self' links.services.disqus.com; font-src 'self' cdnjs.cloudflare.com fonts.gstatic.com fonts.googleapis.com; form-action 'self'; upgrade-insecure-requests;";
var dateHeaderValues = _dateHeaderValueManager.GetDateHeaderValues();
_responseHeadersDirect.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes);
_responseHeadersDirect.SetRawServer("Kestrel", _bytesServer);
}
}
[IterationSetup]
public void Setup()
{
var memoryPool = KestrelMemoryPool.Create();
var options = new PipeOptions(memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
var pair = DuplexPipe.CreateConnectionPair(options, options);
var serviceContext = new ServiceContext
{
DateHeaderValueManager = new DateHeaderValueManager(),
ServerOptions = new KestrelServerOptions(),
Log = new MockTrace(),
HttpParser = new HttpParser<Http1ParsingHandler>()
};
var http1Connection = new Http1Connection(new Http1ConnectionContext
{
ServiceContext = serviceContext,
ConnectionFeatures = new FeatureCollection(),
MemoryPool = memoryPool,
Transport = pair.Transport
});
http1Connection.Reset();
_responseHeadersDirect = (HttpResponseHeaders)http1Connection.ResponseHeaders;
var context = new DefaultHttpContext(http1Connection);
_response = new DefaultHttpResponse(context);
switch (Type)
{
case BenchmarkTypes.ContentLengthNumeric:
ContentLengthNumeric(1);
break;
case BenchmarkTypes.ContentLengthString:
ContentLengthString(1);
break;
case BenchmarkTypes.Plaintext:
Plaintext(1);
break;
case BenchmarkTypes.Common:
Common(1);
break;
case BenchmarkTypes.Unknown:
Unknown(1);
break;
}
}
}
}