Update BenchmarkDotNet and add Http2Connection benchmark (#19482)
This commit is contained in:
parent
c507134320
commit
b1a45eb809
|
|
@ -220,7 +220,7 @@
|
|||
<MicrosoftAspNetCoreAzureAppServicesSiteExtension31PackageVersion>3.1.3</MicrosoftAspNetCoreAzureAppServicesSiteExtension31PackageVersion>
|
||||
<!-- 3rd party dependencies -->
|
||||
<AngleSharpPackageVersion>0.9.9</AngleSharpPackageVersion>
|
||||
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
|
||||
<BenchmarkDotNetPackageVersion>0.12.0</BenchmarkDotNetPackageVersion>
|
||||
<CastleCorePackageVersion>4.2.1</CastleCorePackageVersion>
|
||||
<FSharpCorePackageVersion>4.2.1</FSharpCorePackageVersion>
|
||||
<GoogleProtobufPackageVersion>3.8.0</GoogleProtobufPackageVersion>
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ namespace BenchmarkDotNet.Attributes
|
|||
|
||||
Add(JitOptimizationsValidator.FailOnError);
|
||||
|
||||
Add(Job.Core
|
||||
Add(Job.Default
|
||||
.With(CsProjCoreToolchain.From(NetCoreAppSettings.NetCoreApp21))
|
||||
.With(new GcMode { Server = true })
|
||||
.WithTargetCount(10)
|
||||
.WithIterationCount(10)
|
||||
.WithInvocationCount(1)
|
||||
.WithUnrollFactor(1)
|
||||
.With(RunStrategy.ColdStart));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
// 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.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net.Http.HPack;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
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.Core.Internal.Http2;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
{
|
||||
public class Http2ConnectionBenchmark
|
||||
{
|
||||
private MemoryPool<byte> _memoryPool;
|
||||
private Pipe _pipe;
|
||||
private HttpRequestHeaders _httpRequestHeaders;
|
||||
private Http2Connection _connection;
|
||||
private Http2HeadersEnumerator _requestHeadersEnumerator;
|
||||
private int _currentStreamId;
|
||||
private HPackEncoder _hpackEncoder;
|
||||
private byte[] _headersBuffer;
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_memoryPool = SlabMemoryPoolFactory.Create();
|
||||
|
||||
var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
|
||||
_pipe = new Pipe(options);
|
||||
|
||||
_httpRequestHeaders = new HttpRequestHeaders();
|
||||
_httpRequestHeaders.Append(HeaderNames.Method, new StringValues("GET"));
|
||||
_httpRequestHeaders.Append(HeaderNames.Path, new StringValues("/"));
|
||||
_httpRequestHeaders.Append(HeaderNames.Scheme, new StringValues("http"));
|
||||
_httpRequestHeaders.Append(HeaderNames.Authority, new StringValues("localhost:80"));
|
||||
|
||||
_hpackEncoder = new HPackEncoder();
|
||||
_headersBuffer = new byte[1024 * 16];
|
||||
|
||||
var serviceContext = new ServiceContext
|
||||
{
|
||||
DateHeaderValueManager = new DateHeaderValueManager(),
|
||||
ServerOptions = new KestrelServerOptions(),
|
||||
Log = new KestrelTrace(NullLogger.Instance),
|
||||
SystemClock = new MockSystemClock()
|
||||
};
|
||||
serviceContext.ServerOptions.Limits.Http2.MaxStreamsPerConnection = int.MaxValue;
|
||||
serviceContext.DateHeaderValueManager.OnHeartbeat(default);
|
||||
|
||||
_connection = new Http2Connection(new HttpConnectionContext
|
||||
{
|
||||
MemoryPool = _memoryPool,
|
||||
ConnectionId = "TestConnectionId",
|
||||
Protocols = Core.HttpProtocols.Http2,
|
||||
Transport = new MockDuplexPipe(_pipe.Reader, new NullPipeWriter()),
|
||||
ServiceContext = serviceContext,
|
||||
ConnectionFeatures = new FeatureCollection(),
|
||||
TimeoutControl = new MockTimeoutControl(),
|
||||
});
|
||||
|
||||
_requestHeadersEnumerator = new Http2HeadersEnumerator();
|
||||
|
||||
_currentStreamId = 1;
|
||||
|
||||
_ = _connection.ProcessRequestsAsync(new DummyApplication());
|
||||
|
||||
_pipe.Writer.Write(Http2Connection.ClientPreface);
|
||||
PipeWriterHttp2FrameExtensions.WriteSettings(_pipe.Writer, new Http2PeerSettings());
|
||||
_pipe.Writer.FlushAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public async Task EmptyRequest()
|
||||
{
|
||||
_requestHeadersEnumerator.Initialize(_httpRequestHeaders);
|
||||
PipeWriterHttp2FrameExtensions.WriteStartStream(_pipe.Writer, streamId: _currentStreamId, _requestHeadersEnumerator, _hpackEncoder, _headersBuffer, endStream: true);
|
||||
_currentStreamId += 2;
|
||||
await _pipe.Writer.FlushAsync();
|
||||
}
|
||||
|
||||
[GlobalCleanup]
|
||||
public void Dispose()
|
||||
{
|
||||
_pipe.Writer.Complete();
|
||||
_memoryPool?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
|
|
@ -10,6 +10,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(KestrelSharedSourceRoot)test\DummyApplication.cs" />
|
||||
<Compile Include="$(KestrelSharedSourceRoot)test\PipeWriterHttp2FrameExtensions.cs" />
|
||||
<Compile Include="$(RepoRoot)src\Shared\Buffers.MemoryPool\*.cs" LinkBase="MemoryPool" />
|
||||
<Compile Include="$(KestrelSharedSourceRoot)test\TestApplicationErrorLogger.cs" />
|
||||
<Compile Include="$(KestrelSharedSourceRoot)test\TestHttp1Connection.cs" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// 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.IO.Pipelines;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
{
|
||||
internal class MockDuplexPipe : IDuplexPipe
|
||||
{
|
||||
public MockDuplexPipe(PipeReader input, PipeWriter output)
|
||||
{
|
||||
Input = input;
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public PipeReader Input { get; }
|
||||
public PipeWriter Output { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// 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 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
{
|
||||
internal class MockSystemClock : ISystemClock
|
||||
{
|
||||
public DateTimeOffset UtcNow { get; }
|
||||
public long UtcNowTicks { get; }
|
||||
public DateTimeOffset UtcNowUnsynchronized { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// 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 Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.FlowControl;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
||||
{
|
||||
internal class MockTimeoutControl : ITimeoutControl
|
||||
{
|
||||
public TimeoutReason TimerReason { get; } = TimeoutReason.KeepAlive;
|
||||
|
||||
public void BytesRead(long count)
|
||||
{
|
||||
}
|
||||
|
||||
public void BytesWrittenToBuffer(MinDataRate minRate, long count)
|
||||
{
|
||||
}
|
||||
|
||||
public void CancelTimeout()
|
||||
{
|
||||
}
|
||||
|
||||
public void InitializeHttp2(InputFlowControl connectionInputFlowControl)
|
||||
{
|
||||
}
|
||||
|
||||
public void ResetTimeout(long ticks, TimeoutReason timeoutReason)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetTimeout(long ticks, TimeoutReason timeoutReason)
|
||||
{
|
||||
}
|
||||
|
||||
public void StartRequestBody(MinDataRate minRate)
|
||||
{
|
||||
}
|
||||
|
||||
public void StartTimingRead()
|
||||
{
|
||||
}
|
||||
|
||||
public void StartTimingWrite()
|
||||
{
|
||||
}
|
||||
|
||||
public void StopRequestBody()
|
||||
{
|
||||
}
|
||||
|
||||
public void StopTimingRead()
|
||||
{
|
||||
}
|
||||
|
||||
public void StopTimingWrite()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
{
|
||||
internal class NullPipeWriter : PipeWriter
|
||||
{
|
||||
private byte[] _buffer = new byte[1024 * 128];
|
||||
// Should be large enough for any content attempting to write to the buffer
|
||||
private readonly byte[] _buffer = new byte[1024 * 128];
|
||||
|
||||
public override void Advance(int bytes)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
// 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.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net.Http.HPack;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
|
||||
|
||||
namespace Microsoft.AspNetCore.Testing
|
||||
{
|
||||
internal static class PipeWriterHttp2FrameExtensions
|
||||
{
|
||||
public static void WriteSettings(this PipeWriter writer, Http2PeerSettings clientSettings)
|
||||
{
|
||||
var frame = new Http2Frame();
|
||||
frame.PrepareSettings(Http2SettingsFrameFlags.NONE);
|
||||
var settings = clientSettings.GetNonProtocolDefaults();
|
||||
var payload = new byte[settings.Count * Http2FrameReader.SettingSize];
|
||||
frame.PayloadLength = payload.Length;
|
||||
Http2FrameWriter.WriteSettings(settings, payload);
|
||||
Http2FrameWriter.WriteHeader(frame, writer);
|
||||
writer.Write(payload);
|
||||
}
|
||||
|
||||
public static void WriteStartStream(this PipeWriter writer, int streamId, Http2HeadersEnumerator headers, HPackEncoder hpackEncoder, byte[] headerEncodingBuffer, bool endStream)
|
||||
{
|
||||
var frame = new Http2Frame();
|
||||
frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
|
||||
|
||||
var buffer = headerEncodingBuffer.AsSpan();
|
||||
var done = hpackEncoder.BeginEncode(headers, buffer, out var length);
|
||||
frame.PayloadLength = length;
|
||||
|
||||
if (done)
|
||||
{
|
||||
frame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS;
|
||||
}
|
||||
|
||||
if (endStream)
|
||||
{
|
||||
frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM;
|
||||
}
|
||||
|
||||
Http2FrameWriter.WriteHeader(frame, writer);
|
||||
writer.Write(buffer.Slice(0, length));
|
||||
|
||||
while (!done)
|
||||
{
|
||||
frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);
|
||||
|
||||
done = hpackEncoder.Encode(buffer, out length);
|
||||
frame.PayloadLength = length;
|
||||
|
||||
if (done)
|
||||
{
|
||||
frame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS;
|
||||
}
|
||||
|
||||
Http2FrameWriter.WriteHeader(frame, writer);
|
||||
writer.Write(buffer.Slice(0, length));
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteData(this PipeWriter writer, int streamId, Memory<byte> data, bool endStream)
|
||||
{
|
||||
var frame = new Http2Frame();
|
||||
|
||||
frame.PrepareData(streamId);
|
||||
frame.PayloadLength = data.Length;
|
||||
frame.DataFlags = endStream ? Http2DataFrameFlags.END_STREAM : Http2DataFrameFlags.NONE;
|
||||
|
||||
Http2FrameWriter.WriteHeader(frame, writer);
|
||||
writer.Write(data.Span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -501,56 +501,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
_runningStreams[streamId] = tcs;
|
||||
|
||||
var frame = new Http2Frame();
|
||||
frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
|
||||
|
||||
var buffer = _headerEncodingBuffer.AsSpan();
|
||||
var done = _hpackEncoder.BeginEncode(GetHeadersEnumerator(headers), buffer, out var length);
|
||||
frame.PayloadLength = length;
|
||||
|
||||
if (done)
|
||||
{
|
||||
frame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS;
|
||||
}
|
||||
|
||||
if (endStream)
|
||||
{
|
||||
frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM;
|
||||
}
|
||||
|
||||
Http2FrameWriter.WriteHeader(frame, writableBuffer);
|
||||
writableBuffer.Write(buffer.Slice(0, length));
|
||||
|
||||
while (!done)
|
||||
{
|
||||
frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);
|
||||
|
||||
done = _hpackEncoder.Encode(buffer, out length);
|
||||
frame.PayloadLength = length;
|
||||
|
||||
if (done)
|
||||
{
|
||||
frame.ContinuationFlags = Http2ContinuationFrameFlags.END_HEADERS;
|
||||
}
|
||||
|
||||
Http2FrameWriter.WriteHeader(frame, writableBuffer);
|
||||
writableBuffer.Write(buffer.Slice(0, length));
|
||||
}
|
||||
|
||||
PipeWriterHttp2FrameExtensions.WriteStartStream(writableBuffer, streamId, GetHeadersEnumerator(headers), _hpackEncoder, _headerEncodingBuffer, endStream);
|
||||
return FlushAsync(writableBuffer);
|
||||
}
|
||||
|
||||
private static Http2HeadersEnumerator GetHeadersEnumerator(IEnumerable<KeyValuePair<string, string>> headers)
|
||||
{
|
||||
var groupedHeaders = headers
|
||||
.GroupBy(k => k.Key)
|
||||
.ToDictionary(g => g.Key, g => new StringValues(g.Select(gg => gg.Value).ToArray()));
|
||||
|
||||
var enumerator = new Http2HeadersEnumerator();
|
||||
enumerator.Initialize(groupedHeaders);
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
/* https://tools.ietf.org/html/rfc7540#section-6.2
|
||||
+---------------+
|
||||
|Pad Length? (8)|
|
||||
|
|
@ -704,15 +658,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
|
||||
protected async Task SendSettingsAsync()
|
||||
{
|
||||
var writableBuffer = _pair.Application.Output;
|
||||
var frame = new Http2Frame();
|
||||
frame.PrepareSettings(Http2SettingsFrameFlags.NONE);
|
||||
var settings = _clientSettings.GetNonProtocolDefaults();
|
||||
var payload = new byte[settings.Count * Http2FrameReader.SettingSize];
|
||||
frame.PayloadLength = payload.Length;
|
||||
Http2FrameWriter.WriteSettings(settings, payload);
|
||||
Http2FrameWriter.WriteHeader(frame, writableBuffer);
|
||||
await SendAsync(payload);
|
||||
PipeWriterHttp2FrameExtensions.WriteSettings(_pair.Application.Output, _clientSettings);
|
||||
await FlushAsync(_pair.Application.Output);
|
||||
}
|
||||
|
||||
protected async Task SendSettingsAckWithInvalidLengthAsync(int length)
|
||||
|
|
@ -890,6 +837,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
return done;
|
||||
}
|
||||
|
||||
private Http2HeadersEnumerator GetHeadersEnumerator(IEnumerable<KeyValuePair<string, string>> headers)
|
||||
{
|
||||
var dictionary = headers
|
||||
.GroupBy(g => g.Key)
|
||||
.ToDictionary(g => g.Key, g => new StringValues(g.Select(values => values.Value).ToArray()));
|
||||
|
||||
var headersEnumerator = new Http2HeadersEnumerator();
|
||||
headersEnumerator.Initialize(dictionary);
|
||||
return headersEnumerator;
|
||||
}
|
||||
|
||||
internal Task SendEmptyContinuationFrameAsync(int streamId, Http2ContinuationFrameFlags flags)
|
||||
{
|
||||
var outputWriter = _pair.Application.Output;
|
||||
|
|
@ -923,14 +881,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
protected Task SendDataAsync(int streamId, Memory<byte> data, bool endStream)
|
||||
{
|
||||
var outputWriter = _pair.Application.Output;
|
||||
var frame = new Http2Frame();
|
||||
|
||||
frame.PrepareData(streamId);
|
||||
frame.PayloadLength = data.Length;
|
||||
frame.DataFlags = endStream ? Http2DataFrameFlags.END_STREAM : Http2DataFrameFlags.NONE;
|
||||
|
||||
Http2FrameWriter.WriteHeader(frame, outputWriter);
|
||||
return SendAsync(data.Span);
|
||||
PipeWriterHttp2FrameExtensions.WriteData(outputWriter, streamId, data, endStream);
|
||||
return FlushAsync(outputWriter);
|
||||
}
|
||||
|
||||
protected async Task SendDataWithPaddingAsync(int streamId, Memory<byte> data, byte padLength, bool endStream)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace BenchmarkDotNet.Attributes
|
|||
|
||||
Add(JitOptimizationsValidator.FailOnError);
|
||||
|
||||
Add(Job.Core
|
||||
Add(Job.Default
|
||||
#if NETCOREAPP2_1
|
||||
.With(CsProjCoreToolchain.From(NetCoreAppSettings.NetCoreApp21))
|
||||
#elif NETCOREAPP3_0
|
||||
|
|
|
|||
|
|
@ -22,10 +22,7 @@ namespace BenchmarkDotNet.Attributes
|
|||
Add(MemoryDiagnoser.Default);
|
||||
Add(StatisticColumn.OperationsPerSecond);
|
||||
Add(new ParamsSummaryColumn());
|
||||
Add(DefaultColumnProviders.Statistics, DefaultColumnProviders.Diagnosers, DefaultColumnProviders.Target);
|
||||
|
||||
// TODO: When upgrading to BDN 0.11.1, use Add(DefaultColumnProviders.Descriptor);
|
||||
// DefaultColumnProviders.Target is deprecated
|
||||
Add(DefaultColumnProviders.Statistics, DefaultColumnProviders.Metrics, DefaultColumnProviders.Descriptor);
|
||||
|
||||
Add(JitOptimizationsValidator.FailOnError);
|
||||
|
||||
|
|
@ -36,13 +33,7 @@ namespace BenchmarkDotNet.Attributes
|
|||
|
||||
Add(new CsvExporter(
|
||||
CsvSeparator.Comma,
|
||||
new Reports.SummaryStyle
|
||||
{
|
||||
PrintUnitsInHeader = true,
|
||||
PrintUnitsInContent = false,
|
||||
TimeUnit = Horology.TimeUnit.Microsecond,
|
||||
SizeUnit = SizeUnit.KB
|
||||
}));
|
||||
new Reports.SummaryStyle(printUnitsInHeader: true, printUnitsInContent: false, timeUnit: Horology.TimeUnit.Microsecond, sizeUnit: SizeUnit.KB)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Loggers;
|
||||
using BenchmarkDotNet.Toolchains.InProcess;
|
||||
using BenchmarkDotNet.Toolchains.InProcess.NoEmit;
|
||||
|
||||
namespace BenchmarkDotNet.Attributes
|
||||
{
|
||||
|
|
@ -14,7 +14,7 @@ namespace BenchmarkDotNet.Attributes
|
|||
{
|
||||
Add(ConsoleLogger.Default);
|
||||
|
||||
Add(Job.Dry.With(InProcessToolchain.Instance));
|
||||
Add(Job.Dry.With(InProcessNoEmitToolchain.Instance));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ namespace BenchmarkDotNet.Attributes
|
|||
{
|
||||
public string Id => nameof(ParamsSummaryColumn);
|
||||
public string ColumnName { get; } = "Params";
|
||||
public bool IsDefault(Summary summary, Benchmark benchmark) => false;
|
||||
public string GetValue(Summary summary, Benchmark benchmark) => benchmark.Parameters.DisplayInfo;
|
||||
public bool IsDefault(Summary summary, BenchmarkCase benchmark) => false;
|
||||
public string GetValue(Summary summary, BenchmarkCase benchmark) => benchmark.Parameters.DisplayInfo;
|
||||
public bool IsAvailable(Summary summary) => true;
|
||||
public bool AlwaysShow => true;
|
||||
public ColumnCategory Category => ColumnCategory.Params;
|
||||
|
|
@ -20,7 +20,7 @@ namespace BenchmarkDotNet.Attributes
|
|||
public override string ToString() => ColumnName;
|
||||
public bool IsNumeric => false;
|
||||
public UnitType UnitType => UnitType.Dimensionless;
|
||||
public string GetValue(Summary summary, Benchmark benchmark, ISummaryStyle style) => GetValue(summary, benchmark);
|
||||
public string GetValue(Summary summary, BenchmarkCase benchmark, SummaryStyle style) => GetValue(summary, benchmark);
|
||||
public string Legend => $"Summary of all parameter values";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue