Skip to content

Commit e2dad0e

Browse files
committed
added inbound only TcpSocketChannel benchmark
1 parent e705b7d commit e2dad0e

2 files changed

Lines changed: 144 additions & 0 deletions

File tree

test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
</Choose>
5353
<ItemGroup>
5454
<Compile Include="Properties\AssemblyInfo.cs" />
55+
<Compile Include="Sockets\TcpSocketChannelInboundOnlyPerfSpec.cs" />
5556
<Compile Include="Sockets\TcpSocketChannelPerfSpec.cs" />
5657
<Compile Include="Utilities\CounterHandlerInbound.cs" />
5758
<Compile Include="Utilities\CounterHandlerOutbound.cs" />
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace DotNetty.Transport.Tests.Performance.Sockets
5+
{
6+
using System;
7+
using System.Net;
8+
using System.Net.Sockets;
9+
using System.Text;
10+
using System.Threading;
11+
using System.Threading.Tasks;
12+
using DotNetty.Buffers;
13+
using DotNetty.Codecs;
14+
using DotNetty.Transport.Bootstrapping;
15+
using DotNetty.Transport.Channels;
16+
using DotNetty.Transport.Channels.Sockets;
17+
using DotNetty.Transport.Tests.Performance.Utilities;
18+
using NBench;
19+
20+
public class TcpSocketChannelInboundOnlyPerfSpecs
21+
{
22+
const string InboundThroughputCounterName = "inbound ops";
23+
24+
const string OutboundThroughputCounterName = "outbound ops";
25+
26+
// The number of times we're going to warmup + run each benchmark
27+
public const int IterationCount = 5;
28+
public const int WriteCount = 1000000;
29+
30+
public const int MessagesPerMinute = 1000000;
31+
public TimeSpan Timeout = TimeSpan.FromMinutes((double)WriteCount / MessagesPerMinute);
32+
33+
static readonly IPEndPoint TEST_ADDRESS = new IPEndPoint(IPAddress.IPv6Loopback, 0);
34+
protected readonly ManualResetEventSlim ResetEvent = new ManualResetEventSlim(false);
35+
Counter inboundThroughputCounter;
36+
Counter outboundThroughputCounter;
37+
38+
IChannel serverChannel;
39+
IReadFinishedSignal signal;
40+
41+
protected System.Net.Sockets.Socket ClientSocket;
42+
protected NetworkStream Stream;
43+
44+
byte[] message;
45+
protected ServerBootstrap ServerBoostrap;
46+
protected IEventLoopGroup ServerGroup;
47+
protected IEventLoopGroup WorkerGroup;
48+
49+
IByteBufferAllocator serverBufferAllocator;
50+
51+
static TcpSocketChannelInboundOnlyPerfSpecs()
52+
{
53+
// Disable the logging factory
54+
//LoggingFactory.DefaultFactory = new NoOpLoggerFactory();
55+
}
56+
57+
protected virtual IChannelHandler GetEncoder()
58+
{
59+
return new LengthFieldPrepender(4, false);
60+
}
61+
62+
protected virtual IChannelHandler GetDecoder()
63+
{
64+
return new LengthFieldBasedFrameDecoder(int.MaxValue, 0, 4, 0, 4);
65+
}
66+
67+
[PerfSetup]
68+
public void SetUp(BenchmarkContext context)
69+
{
70+
this.ServerGroup = new MultithreadEventLoopGroup(1);
71+
this.WorkerGroup = new MultithreadEventLoopGroup();
72+
73+
Encoding iso = Encoding.GetEncoding("ISO-8859-1");
74+
this.message = Unpooled.Buffer().WriteInt(3).WriteBytes(iso.GetBytes("ABC")).ToArray();
75+
76+
this.inboundThroughputCounter = context.GetCounter(InboundThroughputCounterName);
77+
this.outboundThroughputCounter = context.GetCounter(OutboundThroughputCounterName);
78+
var counterHandler = new CounterHandlerInbound(this.inboundThroughputCounter);
79+
this.signal = new ManualResetEventSlimReadFinishedSignal(this.ResetEvent);
80+
81+
// using default settings
82+
this.serverBufferAllocator = new PooledByteBufferAllocator();
83+
84+
ServerBootstrap sb = new ServerBootstrap()
85+
.Group(this.ServerGroup, this.WorkerGroup)
86+
.Channel<TcpServerSocketChannel>()
87+
.ChildOption(ChannelOption.Allocator, this.serverBufferAllocator)
88+
.ChildHandler(new ActionChannelInitializer<TcpSocketChannel>(channel => {
89+
channel.Pipeline
90+
.AddLast(this.GetEncoder())
91+
.AddLast(this.GetDecoder())
92+
.AddLast(counterHandler)
93+
.AddLast(new CounterHandlerOutbound(this.outboundThroughputCounter))
94+
.AddLast(new ReadFinishedHandler(this.signal, WriteCount));
95+
}));
96+
97+
// start server
98+
this.serverChannel = sb.BindAsync(TEST_ADDRESS).Result;
99+
100+
// connect to server
101+
var address = (IPEndPoint)this.serverChannel.LocalAddress;
102+
this.ClientSocket = new System.Net.Sockets.Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
103+
this.ClientSocket.Connect(address.Address, address.Port);
104+
105+
this.Stream = new NetworkStream(this.ClientSocket, true);
106+
}
107+
108+
[PerfBenchmark(Description = "Measures how quickly and with how much GC overhead a TcpSocketChannel --> TcpServerSocketChannel connection can decode / encode realistic messages, 100 writes per flush",
109+
NumberOfIterations = IterationCount, RunMode = RunMode.Iterations)]
110+
[CounterMeasurement(InboundThroughputCounterName)]
111+
[CounterMeasurement(OutboundThroughputCounterName)]
112+
[GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)]
113+
[MemoryMeasurement(MemoryMetric.TotalBytesAllocated)]
114+
public void TcpChannel_InboundOnly_Throughput(BenchmarkContext context)
115+
{
116+
for (int i = 0; i < WriteCount; i++)
117+
{
118+
this.Stream.Write(this.message, 0, this.message.Length);
119+
}
120+
this.ResetEvent.Wait(this.Timeout);
121+
}
122+
123+
[PerfCleanup]
124+
public void TearDown()
125+
{
126+
try
127+
{
128+
this.Stream.Close();
129+
}
130+
finally
131+
{
132+
CloseChannel(this.serverChannel);
133+
Task.WaitAll(this.ServerGroup.ShutdownGracefullyAsync(), this.WorkerGroup.ShutdownGracefullyAsync());
134+
}
135+
}
136+
137+
static void CloseChannel(IChannel cc)
138+
{
139+
cc?.CloseAsync().Wait();
140+
}
141+
}
142+
}
143+

0 commit comments

Comments
 (0)