Created
November 24, 2021 09:27
-
-
Save amoerie/76d9455a7c5d022907c3377743d532da to your computer and use it in GitHub Desktop.
NetworkStream vs BufferedStream benchmarks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Threading.Tasks; | |
using BenchmarkDotNet.Attributes; | |
namespace Gists | |
{ | |
[MemoryDiagnoser] | |
public class NetworkBenchmarks | |
{ | |
private TcpListener _listener; | |
[Params(10000)] | |
public int NumWrites { get; set; } | |
[GlobalSetup] | |
public void GlobalSetup() | |
{ | |
_listener = new TcpListener(IPAddress.Loopback, 0); | |
_listener.Start(1); | |
} | |
[GlobalCleanup] | |
public void GlobalCleanup() | |
{ | |
_listener.Stop(); | |
} | |
[Benchmark] | |
public async Task Vanilla() | |
{ | |
await RunWithConnectedNetworkStreamsAsync(async (server, client) => | |
{ | |
await TransferAsync(server, client); | |
}); | |
} | |
[Benchmark] | |
public async Task BufferedClient() | |
{ | |
await RunWithConnectedNetworkStreamsAsync(async (server, client) => | |
{ | |
using (var bufferedClient = new BufferedStream(client)) | |
await TransferAsync(server, bufferedClient); | |
}); | |
} | |
[Benchmark] | |
public async Task BufferedServer() | |
{ | |
await RunWithConnectedNetworkStreamsAsync(async (server, client) => | |
{ | |
using (var bufferedServer = new BufferedStream(server)) | |
await TransferAsync(bufferedServer, client); | |
}); | |
} | |
[Benchmark] | |
public async Task BufferedClientAndServer() | |
{ | |
await RunWithConnectedNetworkStreamsAsync(async (server, client) => | |
{ | |
using (var bufferedServer = new BufferedStream(server)) | |
using (var bufferedClient = new BufferedStream(client)) | |
await TransferAsync(bufferedServer, bufferedClient); | |
}); | |
} | |
Task TransferAsync(Stream server, Stream client) | |
{ | |
return Task.WhenAll( | |
Task.Run(async () => | |
{ | |
for (int i = 0; i < NumWrites; i++) | |
server.WriteByte((byte)i); | |
await server.FlushAsync(); | |
}), | |
Task.Run(() => | |
{ | |
for (int i = 0; i < NumWrites; i++) | |
client.ReadByte(); | |
})); | |
} | |
private async Task RunWithConnectedNetworkStreamsAsync(Func<NetworkStream, NetworkStream, Task> func) | |
{ | |
var clientEndpoint = (IPEndPoint)_listener.LocalEndpoint; | |
using (var client = new TcpClient(clientEndpoint.AddressFamily)) | |
{ | |
Task<TcpClient> remoteTask = _listener.AcceptTcpClientAsync(); | |
Task clientConnectTask = client.ConnectAsync(clientEndpoint.Address, clientEndpoint.Port); | |
await Task.WhenAll(remoteTask, clientConnectTask); | |
using (TcpClient remote = remoteTask.Result) | |
using (NetworkStream serverStream = remote.GetStream()) | |
using (NetworkStream clientStream = client.GetStream()) | |
{ | |
await func(serverStream, clientStream); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Produces: