add some very simple, fairly stupid, benchmarks (#322)
This commit is contained in:
parent
e955c4b9aa
commit
28bf0b445b
|
|
@ -42,3 +42,4 @@ site.min.css
|
||||||
signalr-client/
|
signalr-client/
|
||||||
dist/
|
dist/
|
||||||
global.json
|
global.json
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client-ts", "client-ts", "{
|
||||||
client-ts\package.json = client-ts\package.json
|
client-ts\package.json = client-ts\package.json
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.SignalR.Microbenchmarks", "test\Microsoft.AspNetCore.SignalR.Microbenchmarks\Microsoft.AspNetCore.SignalR.Microbenchmarks.csproj", "{96771B3F-4D18-41A7-A75B-FF38E76AAC89}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -175,6 +177,10 @@ Global
|
||||||
{333526A4-633B-491A-AC45-CC62A0012D1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{333526A4-633B-491A-AC45-CC62A0012D1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{333526A4-633B-491A-AC45-CC62A0012D1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{333526A4-633B-491A-AC45-CC62A0012D1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{333526A4-633B-491A-AC45-CC62A0012D1C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{333526A4-633B-491A-AC45-CC62A0012D1C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{96771B3F-4D18-41A7-A75B-FF38E76AAC89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{96771B3F-4D18-41A7-A75B-FF38E76AAC89}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{96771B3F-4D18-41A7-A75B-FF38E76AAC89}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{96771B3F-4D18-41A7-A75B-FF38E76AAC89}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -205,5 +211,6 @@ Global
|
||||||
{B0D32729-48AA-4841-B52A-2A61B60EED61} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
{B0D32729-48AA-4841-B52A-2A61B60EED61} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||||
{333526A4-633B-491A-AC45-CC62A0012D1C} = {3A76C5A2-79ED-49BC-8BDC-6A3A766FFA1B}
|
{333526A4-633B-491A-AC45-CC62A0012D1C} = {3A76C5A2-79ED-49BC-8BDC-6A3A766FFA1B}
|
||||||
{6CEC3DC2-5B01-45A8-8F0D-8531315DA90B} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
{6CEC3DC2-5B01-45A8-8F0D-8531315DA90B} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||||
|
{96771B3F-4D18-41A7-A75B-FF38E76AAC89} = {6A35B453-52EC-48AF-89CA-D4A69800F131}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.AspNetCore.SignalR.Test.Server\*.csproj" />
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.AspNetCore.SignalR.Test.Server\*.csproj" />
|
||||||
<ExcludeFromTest Include="$(RepositoryRoot)test\WebSocketsTestApp\*.csproj" />
|
<ExcludeFromTest Include="$(RepositoryRoot)test\WebSocketsTestApp\*.csproj" />
|
||||||
|
<ExcludeFromTest Include="$(RepositoryRoot)test\Microsoft.AspNetCore.SignalR.Microbenchmarks\*.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectsToPack Include="$(RepositoryRoot)client-ts\Microsoft.AspNetCore.SignalR.Client.TS\*.csproj" />
|
<ProjectsToPack Include="$(RepositoryRoot)client-ts\Microsoft.AspNetCore.SignalR.Client.TS\*.csproj" />
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.Sockets.Internal.Formatters
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Copy as much as possible from the Unread buffer
|
// Copy as much as possible from the Unread buffer
|
||||||
var toCopy = Math.Min(_state.Length, buffer.Unread.Length);
|
var toCopy = Math.Min(_state.Length - _state.Read, buffer.Unread.Length);
|
||||||
buffer.Unread.Slice(0, toCopy).CopyTo(_state.Payload.Slice(_state.Read));
|
buffer.Unread.Slice(0, toCopy).CopyTo(_state.Payload.Slice(_state.Read));
|
||||||
_state.Read += toCopy;
|
_state.Read += toCopy;
|
||||||
buffer.Advance(toCopy);
|
buffer.Advance(toCopy);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Sequences;
|
|
||||||
|
|
||||||
namespace System
|
namespace System
|
||||||
{
|
{
|
||||||
|
|
@ -11,6 +10,11 @@ namespace System
|
||||||
{
|
{
|
||||||
public static ReadOnlyBytes ToChunkedReadOnlyBytes(this byte[] data, int chunkSize)
|
public static ReadOnlyBytes ToChunkedReadOnlyBytes(this byte[] data, int chunkSize)
|
||||||
{
|
{
|
||||||
|
if (chunkSize == 0)
|
||||||
|
{
|
||||||
|
return new ReadOnlyBytes(data);
|
||||||
|
}
|
||||||
|
|
||||||
var chunks = new List<byte[]>();
|
var chunks = new List<byte[]>();
|
||||||
for (var i = 0; i < data.Length; i += chunkSize)
|
for (var i = 0; i < data.Length; i += chunkSize)
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using BenchmarkDotNet.Columns;
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Diagnosers;
|
||||||
|
using BenchmarkDotNet.Engines;
|
||||||
|
using BenchmarkDotNet.Environments;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using BenchmarkDotNet.Validators;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||||
|
{
|
||||||
|
public class CoreConfig : ManualConfig
|
||||||
|
{
|
||||||
|
public CoreConfig()
|
||||||
|
{
|
||||||
|
Add(JitOptimizationsValidator.FailOnError);
|
||||||
|
Add(MemoryDiagnoser.Default);
|
||||||
|
Add(StatisticColumn.OperationsPerSecond);
|
||||||
|
|
||||||
|
Add(Job.Default
|
||||||
|
.With(Runtime.Core)
|
||||||
|
.WithRemoveOutliers(false)
|
||||||
|
.With(new GcMode() { Server = true })
|
||||||
|
.With(RunStrategy.Throughput)
|
||||||
|
.WithLaunchCount(3)
|
||||||
|
.WithWarmupCount(5)
|
||||||
|
.WithTargetCount(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using Microsoft.AspNetCore.Sockets;
|
||||||
|
using Microsoft.AspNetCore.Sockets.Internal.Formatters;
|
||||||
|
using Microsoft.AspNetCore.Sockets.Tests.Internal;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||||
|
{
|
||||||
|
[Config(typeof(CoreConfig))]
|
||||||
|
public class MessageParserBenchmark
|
||||||
|
{
|
||||||
|
private static readonly Random Random = new Random();
|
||||||
|
private readonly MessageParser _parser = new MessageParser();
|
||||||
|
private ReadOnlyBytes _input;
|
||||||
|
private byte[] _buffer;
|
||||||
|
|
||||||
|
[Params(32, 64)]
|
||||||
|
public int ChunkSize { get; set; }
|
||||||
|
|
||||||
|
[Params(64, 128)]
|
||||||
|
public int MessageLength { get; set; }
|
||||||
|
|
||||||
|
[Params(MessageFormat.Text, MessageFormat.Binary)]
|
||||||
|
public MessageFormat Format { get; set; }
|
||||||
|
|
||||||
|
[Setup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_buffer = new byte[MessageLength];
|
||||||
|
Random.NextBytes(_buffer);
|
||||||
|
var message = new Message(_buffer, MessageType.Binary);
|
||||||
|
var output = new ArrayOutput(MessageLength + 32);
|
||||||
|
if (!MessageFormatter.TryWriteMessage(message, output, Format))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Failed to format message");
|
||||||
|
}
|
||||||
|
_input = output.ToArray().ToChunkedReadOnlyBytes(ChunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void SingleBinaryMessage()
|
||||||
|
{
|
||||||
|
var reader = new BytesReader(_input);
|
||||||
|
if (!_parser.TryParseMessage(ref reader, Format, out _))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Failed to parse");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\..\build\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFrameworks>netcoreapp1.1</TargetFrameworks>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\Common\ByteArrayExtensions.cs" Link="ByteArrayExtensions.cs" />
|
||||||
|
<Compile Include="..\Common\ArrayOutput.cs" Link="ArrayOutput.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets.Common\Microsoft.AspNetCore.Sockets.Common.csproj" />
|
||||||
|
<PackageReference Include="BenchmarkDotNet" Version="0.10.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
BenchmarkSwitcher.FromAssembly(typeof(Program).GetTypeInfo().Assembly).Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -66,9 +66,7 @@ namespace Microsoft.AspNetCore.Sockets.Common.Tests.Internal.Formatters
|
||||||
/* body: */ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6F, 0x72
|
/* body: */ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6F, 0x72
|
||||||
};
|
};
|
||||||
var parser = new MessageParser();
|
var parser = new MessageParser();
|
||||||
var buffer = chunkSize > 0 ?
|
var buffer = encoded.ToChunkedReadOnlyBytes(chunkSize);
|
||||||
encoded.ToChunkedReadOnlyBytes(chunkSize) :
|
|
||||||
new ReadOnlyBytes(encoded);
|
|
||||||
var reader = new BytesReader(buffer);
|
var reader = new BytesReader(buffer);
|
||||||
|
|
||||||
var messages = new List<Message>();
|
var messages = new List<Message>();
|
||||||
|
|
|
||||||
|
|
@ -14,18 +14,19 @@ namespace Microsoft.AspNetCore.Sockets.Common.Tests.Internal.Formatters
|
||||||
public class TextMessageParserTests
|
public class TextMessageParserTests
|
||||||
{
|
{
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("0:T:;", MessageType.Text, "")]
|
[InlineData(0, "0:T:;", MessageType.Text, "")]
|
||||||
[InlineData("3:T:ABC;", MessageType.Text, "ABC")]
|
[InlineData(0, "3:T:ABC;", MessageType.Text, "ABC")]
|
||||||
[InlineData("11:T:A\nR\rC\r\n;DEF;", MessageType.Text, "A\nR\rC\r\n;DEF")]
|
[InlineData(0, "11:T:A\nR\rC\r\n;DEF;", MessageType.Text, "A\nR\rC\r\n;DEF")]
|
||||||
[InlineData("0:C:;", MessageType.Close, "")]
|
[InlineData(0, "0:C:;", MessageType.Close, "")]
|
||||||
[InlineData("17:C:Connection Closed;", MessageType.Close, "Connection Closed")]
|
[InlineData(0, "17:C:Connection Closed;", MessageType.Close, "Connection Closed")]
|
||||||
[InlineData("0:E:;", MessageType.Error, "")]
|
[InlineData(0, "0:E:;", MessageType.Error, "")]
|
||||||
[InlineData("12:E:Server Error;", MessageType.Error, "Server Error")]
|
[InlineData(0, "12:E:Server Error;", MessageType.Error, "Server Error")]
|
||||||
public void ReadTextMessage(string encoded, MessageType messageType, string payload)
|
[InlineData(4, "12:T:Hello, World;", MessageType.Text, "Hello, World")]
|
||||||
|
public void ReadTextMessage(int chunkSize, string encoded, MessageType messageType, string payload)
|
||||||
{
|
{
|
||||||
var parser = new MessageParser();
|
var parser = new MessageParser();
|
||||||
var buffer = Encoding.UTF8.GetBytes(encoded);
|
var buffer = Encoding.UTF8.GetBytes(encoded);
|
||||||
var reader = new BytesReader(buffer);
|
var reader = new BytesReader(buffer.ToChunkedReadOnlyBytes(chunkSize));
|
||||||
|
|
||||||
Assert.True(parser.TryParseMessage(ref reader, MessageFormat.Text, out var message));
|
Assert.True(parser.TryParseMessage(ref reader, MessageFormat.Text, out var message));
|
||||||
Assert.Equal(reader.Index, buffer.Length);
|
Assert.Equal(reader.Index, buffer.Length);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\Common\ArrayOutput.cs" Link="ArrayOutput.cs" />
|
<Compile Include="..\Common\ArrayOutput.cs" Link="ArrayOutput.cs" />
|
||||||
|
<Compile Include="..\Common\ByteArrayExtensions.cs" Link="ByteArrayExtensions.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue