/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Middleware/perf/ResponseCaching.Microbenchmarks/ResponseCachingBenchmark.cs
140 строк
4 KB
Brennan
Add rule to seal internal and private types (#41457)
05 май 2022, 19:26
Не верифицирован
05 май 2022, 19:26
3ea008c
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.IO.Pipelines; using BenchmarkDotNet.Attributes; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.ResponseCaching; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.ObjectPool; using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.WebSockets.Microbenchmarks; public class ResponseCachingBenchmark { private static readonly string _cacheControl = $"{CacheControlHeaderValue.PublicString}, {CacheControlHeaderValue.MaxAgeString}={int.MaxValue}"; private ResponseCachingMiddleware _middleware; private readonly byte[] _data = new byte[1 * 1024 * 1024]; [Params( 100, 64 * 1024, 1 * 1024 * 1024 )] public int Size { get; set; } [GlobalSetup] public void Setup() { _middleware = new ResponseCachingMiddleware( async context => { context.Response.Headers.CacheControl = _cacheControl; await context.Response.BodyWriter.WriteAsync(new ReadOnlyMemory<byte>(_data, 0, Size)); }, Options.Create(new ResponseCachingOptions { SizeLimit = int.MaxValue, // ~2GB MaximumBodySize = 1 * 1024 * 1024, }), NullLoggerFactory.Instance, new DefaultObjectPoolProvider() ); // no need to actually cache as there is a warm-up fase } [Benchmark] public async Task Cache() { var pipe = new Pipe(); var consumer = ConsumeAsync(pipe.Reader, CancellationToken.None); DefaultHttpContext context = CreateHttpContext(pipe); context.Request.Method = HttpMethods.Get; context.Request.Path = "/a"; // don't serve from cache but store result context.Request.Headers.CacheControl = CacheControlHeaderValue.NoCacheString; await _middleware.Invoke(context); await pipe.Writer.CompleteAsync(); await consumer; } [Benchmark] public async Task ServeFromCache() { var pipe = new Pipe(); var consumer = ConsumeAsync(pipe.Reader, CancellationToken.None); DefaultHttpContext context = CreateHttpContext(pipe); context.Request.Method = HttpMethods.Get; context.Request.Path = "/b"; await _middleware.Invoke(context); await pipe.Writer.CompleteAsync(); await consumer; } private static DefaultHttpContext CreateHttpContext(Pipe pipe) { var features = new FeatureCollection(); features.Set<IHttpRequestFeature>(new HttpRequestFeature()); features.Set<IHttpResponseFeature>(new HttpResponseFeature()); features.Set<IHttpResponseBodyFeature>(new PipeResponseBodyFeature(pipe.Writer)); var context = new DefaultHttpContext(features); return context; } private async ValueTask ConsumeAsync(PipeReader reader, CancellationToken cancellationToken) { while (true) { var result = await reader.ReadAsync(cancellationToken); var buffer = result.Buffer; reader.AdvanceTo(buffer.End, buffer.End); if (result.IsCompleted) { break; } } await reader.CompleteAsync(); } private sealed class PipeResponseBodyFeature : IHttpResponseBodyFeature { public PipeResponseBodyFeature(PipeWriter pipeWriter) { Writer = pipeWriter; } public Stream Stream => Writer.AsStream(); public PipeWriter Writer { get; } public Task CompleteAsync() => Writer.CompleteAsync().AsTask(); public void DisableBuffering() { throw new NotImplementedException(); } public Task SendFileAsync(string path, long offset, long? count, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } public Task StartAsync(CancellationToken cancellationToken = default) { throw new NotImplementedException(); } } }