commit 72246984b124e5cab9d9e092d190cbebee97badf parent fadf701ff2271471af70445b9632e6fdfb0f00ae Author: Mikolaj Lenczewski <mikolaj.lenczewski308@gmail.com> Date: Mon, 14 Sep 2020 17:27:30 +0100 Still have memory corruption error. Slowed stuff down by adding the ConnectionDisposed volatile in RawNetworkConnectionBase and by adding checks to SlimObjectPool. Diffstat:
18 files changed, 225 insertions(+), 148 deletions(-)
diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/CombinedMultiClientRawDatagramBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/CombinedMultiClientRawDatagramBenchmark.cs @@ -11,8 +11,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks { internal class CombinedMultiClientRawDatagramBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); private double[] ClientBandwidths; + private volatile EndPoint _serverEndPoint = null; public string Name => "Combined Raw Datagram Network Reader/Writer (Multiple Clients) Benchmark"; @@ -27,7 +28,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks private Task BenchmarkClientTask(object idObj) { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -40,7 +41,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; + EndPoint remoteEndPoint = _serverEndPoint; using RawDatagramNetworkWriter writer = new RawDatagramNetworkWriter(ref rawSocket, defaultRemoteEndPoint, Program.Constants.PacketSize); @@ -89,7 +90,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks public async Task RunAsync() { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -120,6 +123,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/CombinedSingleClientRawDatagramBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/CombinedSingleClientRawDatagramBenchmark.cs @@ -11,8 +11,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks { internal class CombinedSingleClientRawDatagramBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); private double[] ClientBandwidths; + private volatile EndPoint _serverEndPoint = null; public string Name => "Combined Raw Datagram Network Reader/Writer (Single Client) Benchmark"; @@ -27,7 +28,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks private Task BenchmarkClientTask(object idObj) { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -40,7 +41,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; + EndPoint remoteEndPoint = _serverEndPoint; using RawDatagramNetworkWriter writer = new RawDatagramNetworkWriter(ref rawSocket, defaultRemoteEndPoint, Program.Constants.PacketSize); @@ -89,7 +90,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks public async Task RunAsync() { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -116,6 +119,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/RawDatagramNetworkReaderMultiClientBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/RawDatagramNetworkReaderMultiClientBenchmark.cs @@ -11,8 +11,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks { internal class RawDatagramNetworkReaderMultiClientBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); private double[] ClientBandwidths; + private volatile EndPoint _serverEndPoint = null; /// <inheritdoc /> public string Name => "Raw Datagram Network Reader (Multiple Clients) Benchmark"; @@ -28,7 +29,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks private Task BenchmarkClientTask(object idObj) { using Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -39,7 +40,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; + EndPoint remoteEndPoint = _serverEndPoint; lock (typeof(Console)) { @@ -86,7 +87,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks public async Task RunAsync() { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -117,6 +120,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/RawDatagramNetworkReaderSingleClientBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/RawDatagramNetworkReaderSingleClientBenchmark.cs @@ -11,8 +11,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks { internal class RawDatagramNetworkReaderSingleClientBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); private double[] ClientBandwidths; + private volatile EndPoint _serverEndPoint = null; /// <inheritdoc /> public string Name => "Raw Datagram Network Reader (Single Client) Benchmark"; @@ -28,7 +29,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks private Task BenchmarkClientTask(object idObj) { using Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -39,7 +40,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; + EndPoint remoteEndPoint = _serverEndPoint; lock (typeof(Console)) { @@ -86,7 +87,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks public async Task RunAsync() { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -113,6 +116,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/RawDatagramNetworkWriterAsyncBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/RawDatagramNetworkWriterAsyncBenchmark.cs @@ -10,15 +10,18 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks { internal class RawDatagramNetworkWriterAsyncBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private volatile EndPoint _serverEndPoint = null; /// <inheritdoc /> public string Name => "Raw Datagram Network Writer Benchmark (Asynchronous)"; - private static Task ServerTask() + private Task ServerTask() { using Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -49,7 +52,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks public async Task RunAsync() { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -60,21 +63,21 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; - using RawDatagramNetworkWriter writer = new RawDatagramNetworkWriter(ref rawSocket, defaultRemoteEndPoint, Program.Constants.PacketSize); Task serverTask = Task.Factory.StartNew(ServerTask, TaskCreationOptions.LongRunning); + benchmarkHelper.ResetStopwatch(); + + ServerReadyEvent.Wait(); + + EndPoint remoteEndPoint = _serverEndPoint; + lock (typeof(Console)) { Console.WriteLine($"[Client {0}] Starting client at {rawSocket.LocalEndPoint}; sending messages to {remoteEndPoint}"); } - benchmarkHelper.ResetStopwatch(); - - ServerReadyEvent.Wait(); - for (int i = 0; i < Program.Constants.PacketCount; i++) { byte[] packetBuffer = Program.Constants.ServerEncoding.GetBytes($"[Client 0] Hello World! (Packet {i})"); @@ -101,6 +104,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/RawDatagramNetworkWriterSyncBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/RawDatagramNetworkWriterSyncBenchmark.cs @@ -10,15 +10,18 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks { internal class RawDatagramNetworkWriterSyncBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private volatile EndPoint _serverEndPoint = null; /// <inheritdoc /> public string Name => "Raw Datagram Network Writer Benchmark (Synchronous)"; - private static Task ServerTask() + private Task ServerTask() { using Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -46,10 +49,10 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks } /// <inheritdoc /> - public async Task RunAsync() + public Task RunAsync() { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -60,21 +63,21 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; - using RawDatagramNetworkWriter writer = new RawDatagramNetworkWriter(ref rawSocket, defaultRemoteEndPoint, Program.Constants.PacketSize); Task serverTask = Task.Factory.StartNew(ServerTask, TaskCreationOptions.LongRunning); + benchmarkHelper.ResetStopwatch(); + + ServerReadyEvent.Wait(); + + EndPoint remoteEndPoint = _serverEndPoint; + lock (typeof(Console)) { Console.WriteLine($"[Client {0}] Starting client at {rawSocket.LocalEndPoint}; sending messages to {remoteEndPoint}"); } - benchmarkHelper.ResetStopwatch(); - - ServerReadyEvent.Wait(); - for (int i = 0; i < Program.Constants.PacketCount; i++) { byte[] packetBuffer = Program.Constants.ServerEncoding.GetBytes($"[Client 0] Hello World! (Packet {i})"); @@ -101,6 +104,11 @@ namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; + + return Task.CompletedTask; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/CombinedMultiClientRawStreamBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/CombinedMultiClientRawStreamBenchmark.cs @@ -11,8 +11,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { internal class CombinedMultiClientRawStreamBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); private double[] ClientBandwidths; + private volatile EndPoint _serverEndPoint = null; public string Name => "Combined Raw Stream Network Reader/Writer (Multiple Clients) Benchmark"; @@ -28,7 +29,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -41,20 +42,19 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; - using RawStreamNetworkWriter writer = new RawStreamNetworkWriter(ref rawSocket, defaultRemoteEndPoint, Program.Constants.PacketSize); + benchmarkHelper.ResetStopwatch(); + + ServerReadyEvent.Wait(); + EndPoint remoteEndPoint = _serverEndPoint; + rawSocket.Connect(_serverEndPoint); + lock (typeof(Console)) { Console.WriteLine($"[Client {id}] Starting client at {rawSocket.LocalEndPoint}; sending messages to {remoteEndPoint}"); } - benchmarkHelper.ResetStopwatch(); - - ServerReadyEvent.Wait(); - rawSocket.Connect(Program.Constants.ServerEndPoint); - for (int i = 0; i < Program.Constants.PacketCount; i++) { byte[] packetBuffer = Program.Constants.ServerEncoding.GetBytes($"[Client {id}] Hello World! (Packet {i})"); @@ -95,7 +95,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -128,6 +130,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/CombinedSingleClientRawStreamBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/CombinedSingleClientRawStreamBenchmark.cs @@ -10,8 +10,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { internal class CombinedSingleClientRawStreamBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); private double[] ClientBandwidths; + private volatile EndPoint _serverEndPoint = null; public string Name => "Combined Raw Stream Network Reader/Writer (Single Client) Benchmark"; @@ -27,7 +28,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -40,20 +41,19 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; - using RawStreamNetworkWriter writer = new RawStreamNetworkWriter(ref rawSocket, defaultRemoteEndPoint, Program.Constants.PacketSize); + benchmarkHelper.ResetStopwatch(); + + ServerReadyEvent.Wait(); + EndPoint remoteEndPoint = _serverEndPoint; + rawSocket.Connect(_serverEndPoint); + lock (typeof(Console)) { Console.WriteLine($"[Client {id}] Starting client at {rawSocket.LocalEndPoint}; sending messages to {remoteEndPoint}"); } - benchmarkHelper.ResetStopwatch(); - - ServerReadyEvent.Wait(); - rawSocket.Connect(Program.Constants.ServerEndPoint); - for (int i = 0; i < Program.Constants.PacketCount; i++) { byte[] packetBuffer = Program.Constants.ServerEncoding.GetBytes($"[Client {id}] Hello World! (Packet {i})"); @@ -94,7 +94,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -110,7 +112,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks ServerReadyEvent.Set(); - await clientTasks[0]; + await Task.WhenAll(clientTasks); Console.WriteLine($"Total estimated bandwidth: {ClientBandwidths[0]:F3}"); @@ -123,6 +125,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/RawStreamNetworkReaderMultiClientBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/RawStreamNetworkReaderMultiClientBenchmark.cs @@ -11,8 +11,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { internal class RawStreamNetworkReaderMultiClientBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); private double[] ClientBandwidths; + private volatile EndPoint _serverEndPoint = null; /// <inheritdoc /> public string Name => "Raw Stream Network Reader (Multiple Clients) Benchmark"; @@ -29,7 +30,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { using Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - clientSocket.Bind(Program.Constants.ClientEndPoint); + clientSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -41,18 +42,17 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks byte[] receiveBuffer = new byte[Program.Constants.PacketSize + RawStreamPacketHeader.TotalSize]; byte[] packetBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; + benchmarkHelper.ResetStopwatch(); + + ServerReadyEvent.Wait(); + EndPoint remoteEndPoint = _serverEndPoint; + clientSocket.Connect(remoteEndPoint); lock (typeof(Console)) { Console.WriteLine($"[Client {id}] Starting client at {clientSocket.LocalEndPoint}; sending messages to {remoteEndPoint}"); } - benchmarkHelper.ResetStopwatch(); - - ServerReadyEvent.Wait(); - clientSocket.Connect(Program.Constants.ServerEndPoint); - for (int i = 0; i < Program.Constants.PacketCount; i++) { Program.Constants.ServerEncoding.GetBytes($"[Client {id}] Hello World! (Packet {i})").CopyTo(packetBuffer, 0); @@ -116,7 +116,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -150,6 +152,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/RawStreamNetworkReaderSingleClientBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/RawStreamNetworkReaderSingleClientBenchmark.cs @@ -10,8 +10,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { internal class RawStreamNetworkReaderSingleClientBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); private double[] ClientBandwidths; + private volatile EndPoint _serverEndPoint = null; /// <inheritdoc /> public string Name => "Raw Stream Network Reader (Single Client) Benchmark"; @@ -28,7 +29,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { using Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - clientSocket.Bind(Program.Constants.ClientEndPoint); + clientSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -40,18 +41,17 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks byte[] receiveBuffer = new byte[Program.Constants.PacketSize + RawStreamPacketHeader.TotalSize]; byte[] packetBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; + benchmarkHelper.ResetStopwatch(); + + ServerReadyEvent.Wait(); + EndPoint remoteEndPoint = _serverEndPoint; + clientSocket.Connect(remoteEndPoint); lock (typeof(Console)) { Console.WriteLine($"[Client {id}] Starting client at {clientSocket.LocalEndPoint}; sending messages to {remoteEndPoint}"); } - benchmarkHelper.ResetStopwatch(); - - ServerReadyEvent.Wait(); - clientSocket.Connect(Program.Constants.ServerEndPoint); - for (int i = 0; i < Program.Constants.PacketCount; i++) { Program.Constants.ServerEncoding.GetBytes($"[Client {id}] Hello World! (Packet {i})").CopyTo(packetBuffer, 0); @@ -115,7 +115,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -144,6 +146,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/RawStreamNetworkWriterAsyncBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/RawStreamNetworkWriterAsyncBenchmark.cs @@ -10,16 +10,19 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { internal class RawStreamNetworkWriterAsyncBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private volatile EndPoint _serverEndPoint = null; /// <inheritdoc /> public string Name => "Raw Stream Network Writer Benchmark (Asynchronous)"; - private static Task ServerTask() + private Task ServerTask() { using Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -80,7 +83,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -91,22 +94,21 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; - using RawStreamNetworkWriter writer = new RawStreamNetworkWriter(ref rawSocket, defaultRemoteEndPoint, Program.Constants.PacketSize); Task serverTask = Task.Factory.StartNew(ServerTask, TaskCreationOptions.LongRunning); + benchmarkHelper.ResetStopwatch(); + + ServerReadyEvent.Wait(); + EndPoint remoteEndPoint = _serverEndPoint; + rawSocket.Connect(remoteEndPoint); + lock (typeof(Console)) { Console.WriteLine($"[Client {0}] Starting client at {rawSocket.LocalEndPoint}; sending messages to {remoteEndPoint}"); } - benchmarkHelper.ResetStopwatch(); - - ServerReadyEvent.Wait(); - rawSocket.Connect(Program.Constants.ServerEndPoint); - for (int i = 0; i < Program.Constants.PacketCount; i++) { byte[] packetBuffer = Program.Constants.ServerEncoding.GetBytes($"[Client 0] Hello World! (Packet {i})"); @@ -133,6 +135,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + + ServerReadyEvent.Reset(); + _serverEndPoint = null; } } } \ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/RawStreamNetworkWriterSyncBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/RawStreamNetworkWriterSyncBenchmark.cs @@ -10,16 +10,19 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { internal class RawStreamNetworkWriterSyncBenchmark : INetSharpBenchmark { - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(false); + private volatile EndPoint _serverEndPoint = null; /// <inheritdoc /> public string Name => "Raw Stream Network Writer Benchmark (Synchronous)"; - private static Task ServerTask() + private Task ServerTask() { using Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ServerEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); + + _serverEndPoint = rawSocket.LocalEndPoint; try { @@ -80,7 +83,7 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks { Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - rawSocket.Bind(Program.Constants.ClientEndPoint); + rawSocket.Bind(Program.Constants.DefaultEndPoint); try { @@ -91,22 +94,21 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks byte[] sendBuffer = new byte[Program.Constants.PacketSize]; byte[] receiveBuffer = new byte[Program.Constants.PacketSize]; - EndPoint remoteEndPoint = Program.Constants.ServerEndPoint; - using RawStreamNetworkWriter writer = new RawStreamNetworkWriter(ref rawSocket, defaultRemoteEndPoint, Program.Constants.PacketSize); Task serverTask = Task.Factory.StartNew(ServerTask, TaskCreationOptions.LongRunning); + benchmarkHelper.ResetStopwatch(); + + ServerReadyEvent.Wait(); + EndPoint remoteEndPoint = _serverEndPoint; + rawSocket.Connect(remoteEndPoint); + lock (typeof(Console)) { Console.WriteLine($"[Client {0}] Starting client at {rawSocket.LocalEndPoint}; sending messages to {remoteEndPoint}"); } - benchmarkHelper.ResetStopwatch(); - - ServerReadyEvent.Wait(); - rawSocket.Connect(Program.Constants.ServerEndPoint); - for (int i = 0; i < Program.Constants.PacketCount; i++) { byte[] packetBuffer = Program.Constants.ServerEncoding.GetBytes($"[Client 0] Hello World! (Packet {i})"); @@ -134,6 +136,9 @@ namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks rawSocket.Close(); rawSocket.Dispose(); + ServerReadyEvent.Reset(); + _serverEndPoint = null; + return Task.CompletedTask; } } diff --git a/NetSharp/NetSharp.Benchmarks/Program.cs b/NetSharp/NetSharp.Benchmarks/Program.cs @@ -9,11 +9,23 @@ namespace NetSharp.Benchmarks { internal class Program { - private static readonly List<INetSharpBenchmark> Benchmarks; + private static readonly List<INetSharpBenchmark> Benchmarks = new List<INetSharpBenchmark>(); - static Program() + private static void Main() + { + while (true) + { + ResetBenchmarks(); + + GC.Collect(); + + PickBenchmark(); + } + } + + private static void ResetBenchmarks() { - Benchmarks = new List<INetSharpBenchmark>(); + Benchmarks.Clear(); foreach (Type type in Assembly.GetCallingAssembly().GetTypes()) { @@ -30,16 +42,6 @@ namespace NetSharp.Benchmarks } } - private static void Main() - { - while (true) - { - GC.Collect(); - - PickBenchmark(); - } - } - private static void PickBenchmark() { const string allBenchmarkIdentifier = "XX"; @@ -109,19 +111,14 @@ namespace NetSharp.Benchmarks public static class Constants { - private const int DefaultPort = 44231; - private static readonly IPAddress DefaultAddress = IPAddress.Loopback; - #if DEBUG // Packet counts of over 10_000 can take a long time, depending on the packet size and number of clients - public const int PacketSize = 4096, PacketCount = 10_000, ClientCount = 1; + public const int PacketSize = 4096, PacketCount = 1_000_000, ClientCount = 10; #else // RELEASE public const int PacketSize = 8192, PacketCount = 1_000_000, ClientCount = 10; #endif - - public static readonly EndPoint ClientEndPoint = new IPEndPoint(DefaultAddress, 0); public static readonly Encoding ServerEncoding = Encoding.UTF8; - public static readonly EndPoint ServerEndPoint = new IPEndPoint(DefaultAddress, DefaultPort); + public static readonly EndPoint DefaultEndPoint = new IPEndPoint(IPAddress.Loopback, 0); } } } \ No newline at end of file diff --git a/NetSharp/NetSharp/NetSharp.xml b/NetSharp/NetSharp/NetSharp.xml @@ -228,7 +228,7 @@ </member> <member name="M:NetSharp.Raw.RawNetworkConnectionBase.#ctor(System.Net.Sockets.Socket@,System.Net.EndPoint,System.Int32,System.Int32,System.UInt32)"> <summary> - Initialises a new instance of the <see cref="T:NetSharp.Raw.RawNetworkConnectionBase"/> class. + Initialises a new instance of the <see cref="T:NetSharp.Raw.RawNetworkConnectionBase" /> class. </summary> <param name="rawConnection"> The underlying <see cref="T:System.Net.Sockets.Socket" /> to use for the connection. @@ -274,7 +274,8 @@ </member> <member name="M:NetSharp.Raw.RawNetworkConnectionBase.CleanupTransmissionBufferAndState(System.Net.Sockets.SocketAsyncEventArgs)"> <summary> - Performs cleanup on the given <paramref name="args" /> instance. + Performs cleanup on the given <paramref name="args" /> instance. Neither the given <paramref name="args"/> instance, nor the + <see cref="P:System.Net.Sockets.SocketAsyncEventArgs.Buffer" /> or <see cref="P:System.Net.Sockets.SocketAsyncEventArgs.MemoryBuffer" /> attached to it can be used after this call. </summary> <param name="args"> The used <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> that can be cleaned up to be reused. @@ -291,7 +292,7 @@ Allows for inheritors to dispose of their own resources. </summary> <param name="disposing"> - Whether the <see cref="M:NetSharp.Raw.RawNetworkConnectionBase.Dispose"/> method is being called. + Whether the <see cref="M:NetSharp.Raw.RawNetworkConnectionBase.Dispose" /> method is being called. </param> </member> <member name="M:NetSharp.Raw.RawNetworkConnectionBase.ResetStateObject(System.Net.Sockets.SocketAsyncEventArgs@)"> diff --git a/NetSharp/NetSharp/Raw/Datagram/RawDatagramNetworkReader.cs b/NetSharp/NetSharp/Raw/Datagram/RawDatagramNetworkReader.cs @@ -153,7 +153,6 @@ namespace NetSharp.Raw.Datagram { case SocketAsyncOperation.ReceiveFrom: StartDefaultReceiveFrom(); - CompleteReceiveFrom(args); break; @@ -165,16 +164,19 @@ namespace NetSharp.Raw.Datagram private void StartDefaultReceiveFrom() { - SocketAsyncEventArgs args = ArgsPool.Rent(); + if (!ConnectionDisposed) + { + SocketAsyncEventArgs args = ArgsPool.Rent(); - ConfigureAsyncReceiveFrom(args); + ConfigureAsyncReceiveFrom(args); - StartReceiveFrom(args); + StartReceiveFrom(args); + } } private void StartReceiveFrom(SocketAsyncEventArgs args) { - if (Connection.ReceiveFromAsync(args)) + if (!ConnectionDisposed && Connection.ReceiveFromAsync(args)) { return; } @@ -185,7 +187,7 @@ namespace NetSharp.Raw.Datagram private void StartSendTo(SocketAsyncEventArgs args) { - if (Connection.SendToAsync(args)) + if (!ConnectionDisposed && Connection.SendToAsync(args)) { return; } diff --git a/NetSharp/NetSharp/Raw/RawNetworkConnectionBase.cs b/NetSharp/NetSharp/Raw/RawNetworkConnectionBase.cs @@ -30,6 +30,8 @@ namespace NetSharp.Raw /// </summary> protected const int MaxDatagramSize = ushort.MaxValue - 28; // 65535 - 28 = 65507 + protected volatile bool ConnectionDisposed; + private readonly SlimObjectPool<SocketAsyncEventArgs> argsPool; private readonly ArrayPool<byte> bufferPool; @@ -39,7 +41,7 @@ namespace NetSharp.Raw private readonly EndPoint defaultEndPoint; /// <summary> - /// Initialises a new instance of the <see cref="RawNetworkConnectionBase"/> class. + /// Initialises a new instance of the <see cref="RawNetworkConnectionBase" /> class. /// </summary> /// <param name="rawConnection"> /// The underlying <see cref="Socket" /> to use for the connection. @@ -113,7 +115,8 @@ namespace NetSharp.Raw protected abstract bool CanReuseStateObject(ref SocketAsyncEventArgs instance); /// <summary> - /// Performs cleanup on the given <paramref name="args" /> instance. + /// Performs cleanup on the given <paramref name="args" /> instance. Neither the given <paramref name="args"/> instance, nor the + /// <see cref="SocketAsyncEventArgs.Buffer" /> or <see cref="SocketAsyncEventArgs.MemoryBuffer" /> attached to it can be used after this call. /// </summary> /// <param name="args"> /// The used <see cref="SocketAsyncEventArgs" /> that can be cleaned up to be reused. @@ -143,16 +146,19 @@ namespace NetSharp.Raw /// Allows for inheritors to dispose of their own resources. /// </summary> /// <param name="disposing"> - /// Whether the <see cref="Dispose()"/> method is being called. + /// Whether the <see cref="Dispose()" /> method is being called. /// </param> protected virtual void Dispose(bool disposing) { - if (!disposing) + ConnectionDisposed = true; + + if (disposing) { - return; + // dispose of managed resources + argsPool?.Dispose(); } - argsPool.Dispose(); + // dispose of unmanaged resources } /// <inheritdoc cref="SlimObjectPool{T}.ResetObjectDelegate" /> diff --git a/NetSharp/NetSharp/Raw/Stream/RawStreamNetworkReader.cs b/NetSharp/NetSharp/Raw/Stream/RawStreamNetworkReader.cs @@ -117,9 +117,6 @@ namespace NetSharp.Raw.Stream switch (args.SocketError) { case SocketError.Success: - // ensure that the serverside client socket will be successfully, gracefully shutdown after the conection ends - args.AcceptSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); - // the buffer is set to allow a simpler ConfigureReceiveHeader() implemetation. Since returning an empty buffer is ignored in the // array pool, this allows us to just return the last assigned buffer in the ConfigureXXX() method to the pool (this means that // usually we will usually be returning the ResponseDataBuffer). @@ -345,7 +342,7 @@ namespace NetSharp.Raw.Stream private void StartAccept(SocketAsyncEventArgs args) { - if (Connection.AcceptAsync(args)) + if (!ConnectionDisposed && Connection.AcceptAsync(args)) { return; } @@ -356,9 +353,12 @@ namespace NetSharp.Raw.Stream private void StartDefaultAccept() { - SocketAsyncEventArgs args = ArgsPool.Rent(); + if (!ConnectionDisposed) + { + SocketAsyncEventArgs args = ArgsPool.Rent(); - StartAccept(args); + StartAccept(args); + } } private void StartOrContinueReceive(SocketAsyncEventArgs args) diff --git a/NetSharp/NetSharp/Utils/SlimObjectPool.cs b/NetSharp/NetSharp/Utils/SlimObjectPool.cs @@ -108,9 +108,14 @@ namespace NetSharp.Utils [MethodImpl(MethodImplOptions.Synchronized)] public T Rent() { - bool rentedInstance = objectBuffer.TryTake(out T result); + bool successfullyRentedInstance = objectBuffer.TryTake(out T instance); - return rentedInstance ? result : createObjectDelegate(); + if (successfullyRentedInstance) + { + return instance; + } + + return createObjectDelegate(); } /// <summary> @@ -126,14 +131,12 @@ namespace NetSharp.Utils { resetObjectDelegate(ref instance); - objectBuffer.TryAdd(instance); - - // bool couldRebuffer = false; + bool successfullyRebufferedInstance = objectBuffer.TryAdd(instance); - // while (!couldRebuffer) - // { - // couldRebuffer = objectBuffer.TryAdd(instance); - // } + if (!successfullyRebufferedInstance) + { + destroyObjectDelegate(instance); + } } else {