Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit 531c7cf

Browse files
More micro benchmarks (#1158)
- Hub Protocol benchmark - Broadcast benchmark - Run benchmarks validation during builds
1 parent 887e22e commit 531c7cf

File tree

12 files changed

+232
-27
lines changed

12 files changed

+232
-27
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using System.Threading.Channels;
3+
using System.Threading.Tasks;
4+
using BenchmarkDotNet.Attributes;
5+
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
6+
using Microsoft.AspNetCore.Sockets;
7+
using Microsoft.AspNetCore.Sockets.Internal;
8+
9+
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
10+
{
11+
[ParameterizedJobConfig(typeof(CoreConfig))]
12+
public class BroadcastBenchmark
13+
{
14+
private DefaultHubLifetimeManager<Hub> _hubLifetimeManager;
15+
private HubContext<Hub> _hubContext;
16+
17+
[Params(1, 10, 1000)]
18+
public int Connections;
19+
20+
[GlobalSetup]
21+
public void GlobalSetup()
22+
{
23+
_hubLifetimeManager = new DefaultHubLifetimeManager<Hub>();
24+
var options = new UnboundedChannelOptions { AllowSynchronousContinuations = true };
25+
26+
for (var i = 0; i < Connections; ++i)
27+
{
28+
var transportToApplication = Channel.CreateUnbounded<byte[]>(options);
29+
var applicationToTransport = Channel.CreateUnbounded<byte[]>(options);
30+
31+
var application = ChannelConnection.Create<byte[]>(input: applicationToTransport, output: transportToApplication);
32+
var transport = ChannelConnection.Create<byte[]>(input: transportToApplication, output: applicationToTransport);
33+
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), transport, application);
34+
35+
_hubLifetimeManager.OnConnectedAsync(new HubConnectionContext(Channel.CreateUnbounded<HubMessage>(), connection)).Wait();
36+
}
37+
38+
_hubContext = new HubContext<Hub>(_hubLifetimeManager);
39+
}
40+
41+
[Benchmark]
42+
public Task InvokeAsyncAll()
43+
{
44+
return _hubContext.All.InvokeAsync("Method");
45+
}
46+
}
47+
}

benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/CoreConfig.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,31 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Text;
4-
using BenchmarkDotNet.Columns;
1+
using BenchmarkDotNet.Columns;
52
using BenchmarkDotNet.Configs;
63
using BenchmarkDotNet.Diagnosers;
74
using BenchmarkDotNet.Engines;
8-
using BenchmarkDotNet.Environments;
95
using BenchmarkDotNet.Jobs;
106
using BenchmarkDotNet.Validators;
117

128
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
139
{
1410
public class CoreConfig : ManualConfig
1511
{
16-
public CoreConfig()
12+
public CoreConfig() : this(Job.Core)
1713
{
14+
// Here because build.cmd calls the other constructor
15+
// and this setting will complain about non-release builds
1816
Add(JitOptimizationsValidator.FailOnError);
17+
}
18+
19+
public CoreConfig(Job job)
20+
{
21+
Add(DefaultConfig.Instance);
1922
Add(MemoryDiagnoser.Default);
2023
Add(StatisticColumn.OperationsPerSecond);
2124

22-
Add(Job.Default
23-
.With(BenchmarkDotNet.Environments.Runtime.Core)
25+
Add(job
26+
.With(RunStrategy.Throughput)
2427
.WithRemoveOutliers(false)
2528
.With(new GcMode() { Server = true })
26-
.With(RunStrategy.Throughput)
2729
.WithLaunchCount(3)
2830
.WithWarmupCount(5)
2931
.WithTargetCount(10));
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System;
2+
using BenchmarkDotNet.Attributes;
3+
using Microsoft.AspNetCore.SignalR.Internal;
4+
using Microsoft.AspNetCore.SignalR.Internal.Encoders;
5+
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
6+
7+
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
8+
{
9+
[ParameterizedJobConfig(typeof(CoreConfig))]
10+
public class HubProtocolBenchmark
11+
{
12+
private HubProtocolReaderWriter _hubProtocolReaderWriter;
13+
private byte[] _binaryInput;
14+
private TestBinder _binder;
15+
private HubMessage _hubMessage;
16+
17+
[Params(Message.NoArguments, Message.FewArguments, Message.ManyArguments, Message.LargeArguments)]
18+
public Message Input { get; set; }
19+
20+
[Params(Protocol.MsgPack, Protocol.Json)]
21+
public Protocol HubProtocol { get; set; }
22+
23+
[GlobalSetup]
24+
public void GlobalSetup()
25+
{
26+
switch (HubProtocol)
27+
{
28+
case Protocol.MsgPack:
29+
_hubProtocolReaderWriter = new HubProtocolReaderWriter(new MessagePackHubProtocol(), new PassThroughEncoder());
30+
break;
31+
case Protocol.Json:
32+
_hubProtocolReaderWriter = new HubProtocolReaderWriter(new JsonHubProtocol(), new PassThroughEncoder());
33+
break;
34+
}
35+
36+
switch (Input)
37+
{
38+
case Message.NoArguments:
39+
_hubMessage = new InvocationMessage("123", true, "Target", null);
40+
break;
41+
case Message.FewArguments:
42+
_hubMessage = new InvocationMessage("123", true, "Target", null, 1, "Foo", 2.0f);
43+
break;
44+
case Message.ManyArguments:
45+
_hubMessage = new InvocationMessage("123", true, "Target", null, 1, "string", 2.0f, true, (byte)9, new byte[] { 5, 4, 3, 2, 1 }, 'c', 123456789101112L);
46+
break;
47+
case Message.LargeArguments:
48+
_hubMessage = new InvocationMessage("123", true, "Target", null, new string('F', 10240), new byte[10240]);
49+
break;
50+
}
51+
52+
_binaryInput = GetBytes(_hubMessage);
53+
_binder = new TestBinder(_hubMessage);
54+
}
55+
56+
[Benchmark]
57+
public void ReadSingleMessage()
58+
{
59+
if (!_hubProtocolReaderWriter.ReadMessages(_binaryInput, _binder, out var _))
60+
{
61+
throw new InvalidOperationException("Failed to read message");
62+
}
63+
}
64+
65+
[Benchmark]
66+
public void WriteSingleMessage()
67+
{
68+
if (_hubProtocolReaderWriter.WriteMessage(_hubMessage).Length != _binaryInput.Length)
69+
{
70+
throw new InvalidOperationException("Failed to write message");
71+
}
72+
}
73+
74+
public enum Protocol
75+
{
76+
MsgPack = 0,
77+
Json = 1
78+
}
79+
80+
public enum Message
81+
{
82+
NoArguments = 0,
83+
FewArguments = 1,
84+
ManyArguments = 2,
85+
LargeArguments = 3
86+
}
87+
88+
private byte[] GetBytes(HubMessage hubMessage)
89+
{
90+
return _hubProtocolReaderWriter.WriteMessage(_hubMessage);
91+
}
92+
}
93+
}

benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/MessageParserBenchmark.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
77
{
8-
[Config(typeof(CoreConfig))]
8+
[ParameterizedJobConfig(typeof(CoreConfig))]
99
public class MessageParserBenchmark
1010
{
1111
private static readonly Random Random = new Random();

benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks.csproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
5+
<TargetFramework>netcoreapp2.0</TargetFramework>
66
</PropertyGroup>
77

88
<ItemGroup>
9+
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Core\Microsoft.AspNetCore.SignalR.Core.csproj" />
910
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SignalR.Common\Microsoft.AspNetCore.SignalR.Common.csproj" />
11+
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Sockets\Microsoft.AspNetCore.Sockets.csproj" />
1012
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetPackageVersion)" />
13+
<PackageReference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)" />
14+
<PackageReference Include="System.Threading.Channels" Version="$(SystemThreadingChannelsPackageVersion)" />
1115
</ItemGroup>
1216

1317
</Project>

benchmarks/Microsoft.AspNetCore.SignalR.Microbenchmarks/Program.cs

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Linq;
6+
using Microsoft.AspNetCore.SignalR.Internal;
7+
using Microsoft.AspNetCore.SignalR.Internal.Protocol;
8+
9+
namespace Microsoft.AspNetCore.SignalR.Microbenchmarks
10+
{
11+
public class TestBinder : IInvocationBinder
12+
{
13+
private readonly Type[] _paramTypes;
14+
private readonly Type _returnType;
15+
16+
public TestBinder(HubMessage expectedMessage)
17+
{
18+
switch (expectedMessage)
19+
{
20+
case StreamInvocationMessage i:
21+
_paramTypes = i.Arguments?.Select(a => a?.GetType() ?? typeof(object))?.ToArray();
22+
break;
23+
case InvocationMessage i:
24+
_paramTypes = i.Arguments?.Select(a => a?.GetType() ?? typeof(object))?.ToArray();
25+
break;
26+
case StreamItemMessage s:
27+
_returnType = s.Item?.GetType() ?? typeof(object);
28+
break;
29+
case CompletionMessage c:
30+
_returnType = c.Result?.GetType() ?? typeof(object);
31+
break;
32+
}
33+
}
34+
35+
public TestBinder() : this(null, null) { }
36+
public TestBinder(Type[] paramTypes) : this(paramTypes, null) { }
37+
public TestBinder(Type returnType) : this(null, returnType) { }
38+
public TestBinder(Type[] paramTypes, Type returnType)
39+
{
40+
_paramTypes = paramTypes;
41+
_returnType = returnType;
42+
}
43+
44+
public Type[] GetParameterTypes(string methodName)
45+
{
46+
if (_paramTypes != null)
47+
{
48+
return _paramTypes;
49+
}
50+
throw new InvalidOperationException("Unexpected binder call");
51+
}
52+
53+
public Type GetReturnType(string invocationId)
54+
{
55+
if (_returnType != null)
56+
{
57+
return _returnType;
58+
}
59+
throw new InvalidOperationException("Unexpected binder call");
60+
}
61+
}
62+
}

build/dependencies.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
</PropertyGroup>
55
<PropertyGroup Label="Package Versions">
66
<BenchmarkDotNetPackageVersion>0.10.9</BenchmarkDotNetPackageVersion>
7+
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.1.0-preview1-27579</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
78
<BuildBundlerMinifierPackageVersion>2.4.337</BuildBundlerMinifierPackageVersion>
89
<GoogleProtobufPackageVersion>3.1.0</GoogleProtobufPackageVersion>
910
<InternalAspNetCoreSdkPackageVersion>2.1.0-preview1-15549</InternalAspNetCoreSdkPackageVersion>

build/repo.props

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<Project>
2+
<PropertyGroup>
3+
<EnableBenchmarkValidation>true</EnableBenchmarkValidation>
4+
</PropertyGroup>
25
<ItemGroup>
36
<ProjectsToPack Include="$(RepositoryRoot)client-ts\Microsoft.AspNetCore.SignalR.Client.TS\*.csproj" />
47
</ItemGroup>

samples/SocketsSample/wwwroot/hubs.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ <h4>Private Message</h4>
104104
connectButton.disabled = true;
105105
disconnectButton.disabled = false;
106106
console.log('http://' + document.location.host + '/' + hubRoute);
107-
connection = new signalR.HubConnection(hubRoute, logger, { transport: transportType, logger: logger });
107+
connection = new signalR.HubConnection(hubRoute, { transport: transportType, logging: logger });
108108
connection.on('Send', function(msg) {
109109
addLine('message-list', msg);
110110
});

0 commit comments

Comments
 (0)