]> git.deb.at Git - rhonda/impostor.hazel.git/commitdiff
Reduce allocations when receiving packets
authorForest <chocozilla@gmail.com>
Mon, 17 Dec 2018 00:29:14 +0000 (16:29 -0800)
committerForest <chocozilla@gmail.com>
Mon, 17 Dec 2018 00:29:14 +0000 (16:29 -0800)
Hazel.UnitTests/TestHelper.cs
Hazel.UnitTests/UdpConnectionTests.cs
Hazel/Connection.cs
Hazel/ConnectionListener.cs
Hazel/DataReceivedEventArgs.cs
Hazel/MessageReader.cs
Hazel/NewConnectionEventArgs.cs
Hazel/Udp/UdpConnection.Fragmented.cs
Hazel/Udp/UdpConnection.cs
Hazel/Udp/UdpConnectionListener.cs

index 1436ff6549a5f7e1d79e6d8d169afd68cfe1452d..08c44b752ebc8e461af1443f2bd1d498dab9ed6d 100644 (file)
@@ -35,11 +35,11 @@ namespace Hazel.UnitTests
             {
                 Trace.WriteLine("Data was received correctly.");
 
-                Assert.AreEqual(data.Length, args.Bytes.Length);
+                Assert.AreEqual(data.Length, args.Message.Length);
 
                 for (int i = 0; i < data.Length; i++)
                 {
-                    Assert.AreEqual(data[i], args.Bytes[i]);
+                    Assert.AreEqual(data[i], args.Message.ReadByte());
                 }
 
                 Assert.AreEqual(sendOption, args.SendOption);
@@ -72,11 +72,11 @@ namespace Hazel.UnitTests
                 {
                     Trace.WriteLine("Data was received correctly.");
 
-                    Assert.AreEqual(data.Length, innerArgs.Bytes.Length);
+                    Assert.AreEqual(data.Length, innerArgs.Message.Length);
 
                     for (int i = 0; i < data.Length; i++)
                     {
-                        Assert.AreEqual(data[i], innerArgs.Bytes[i]);
+                        Assert.AreEqual(data[i], innerArgs.Message.ReadByte());
                     }
 
                     Assert.AreEqual(sendOption, innerArgs.SendOption);
index 3476653b326028dd8a0abcefb03167548dfff593..575cdbf68c2e4a5e01650de70f7c8fc442f22cb8 100644 (file)
@@ -39,31 +39,41 @@ namespace Hazel.UnitTests
         [TestMethod]
         public void UdpHandshakeTest()
         {
+            byte[] TestData = new byte[] { 1, 2, 3, 4, 5, 6 };
             using (UdpConnectionListener listener = new UdpConnectionListener(new NetworkEndPoint(IPAddress.Any, 4296, IPMode.IPv4)))
             using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4)))
             {
                 listener.Start();
 
+                MessageReader output = null;
                 listener.NewConnection += delegate (object sender, NewConnectionEventArgs e)
                 {
-                    Assert.IsTrue(Enumerable.SequenceEqual(e.HandshakeData, new byte[] { 1, 2, 3, 4, 5, 6 }));
+                    output = e.HandshakeData;
                 };
 
-                connection.Connect(new byte[] { 1, 2, 3, 4, 5, 6 });
+                connection.Connect(TestData);
+
+                Thread.Sleep(10);
+                for (int i = 0; i < TestData.Length; ++i)
+                {
+                    Assert.AreEqual(TestData[i], output.ReadByte());
+                }
             }
         }
 
         [TestMethod]
         public void UdpUnreliableMessageSendTest()
         {
+            byte[] TestData = new byte[] { 1, 2, 3, 4, 5, 6 };
             using (UdpConnectionListener listener = new UdpConnectionListener(new NetworkEndPoint(IPAddress.Any, 4296, IPMode.IPv4)))
             using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4)))
             {
+                MessageReader output = null;
                 listener.NewConnection += delegate (object sender, NewConnectionEventArgs e)
                 {
                     e.Connection.DataReceived += delegate (object s, DataReceivedEventArgs evt)
                     {
-                        Assert.IsTrue(Enumerable.SequenceEqual(evt.Bytes, new byte[] { 1, 2, 3, 4, 5, 6 }));
+                        output = evt.Message;
                     };
                 };
 
@@ -73,10 +83,16 @@ namespace Hazel.UnitTests
                 for (int i = 0; i < 4; ++i)
                 {
                     var msg = MessageWriter.Get(SendOption.None);
-                    msg.Write(new byte[] { 1, 2, 3, 4, 5, 6 });
+                    msg.Write(TestData);
                     connection.Send(msg);
                     msg.Recycle();
                 }
+
+                Thread.Sleep(10);
+                for (int i = 0; i < TestData.Length; ++i)
+                {
+                    Assert.AreEqual(TestData[i], output.ReadByte());
+                }
             }
         }
 
@@ -91,7 +107,7 @@ namespace Hazel.UnitTests
                 {
                     e.Connection.DataReceived += delegate (object s, DataReceivedEventArgs evt)
                     {
-                        Assert.IsTrue(Enumerable.SequenceEqual(evt.Bytes, new byte[] { 3, 4 }));
+                        Assert.IsTrue(Enumerable.SequenceEqual(evt.Message.Buffer, new byte[] { 3, 4 }));
                     };
                 };
 
@@ -280,13 +296,18 @@ namespace Hazel.UnitTests
 
                     Thread.Sleep(1050);    //Enough time for ~10 keep alive packets
 
-                    Assert.IsTrue(
-                        args.Connection.Statistics.TotalBytesSent >= 30 &&
-                        args.Connection.Statistics.TotalBytesSent <= 50,
-                        "Sent: " + args.Connection.Statistics.TotalBytesSent
-                    );
-
-                    mutex.Set();
+                    try
+                    {
+                        Assert.IsTrue(
+                            args.Connection.Statistics.TotalBytesSent >= 30 &&
+                            args.Connection.Statistics.TotalBytesSent <= 50,
+                            "Sent: " + args.Connection.Statistics.TotalBytesSent
+                        );
+                    }
+                    finally
+                    {
+                        mutex.Set();
+                    }
                 };
 
                 listener.Start();
index 5bb765f5a65dc16bde0e03bf819adfe6a9befb6c..5a02b40e2655d71f30c6d3b5d35cd32bf7a1a421 100644 (file)
@@ -236,17 +236,17 @@ namespace Hazel
         /// <summary>
         ///     Invokes the DataReceived event.
         /// </summary>
-        /// <param name="bytes">The bytes received.</param>
+        /// <param name="msg">The bytes received.</param>
         /// <param name="sendOption">The <see cref="SendOption"/> the message was received with.</param>
         /// <remarks>
         ///     Invokes the <see cref="DataReceived"/> event on this connection to alert subscribers a new message has been
         ///     received. The bytes and the send option that the message was sent with should be passed in to give to the
         ///     subscribers.
         /// </remarks>
-        protected void InvokeDataReceived(byte[] bytes, SendOption sendOption, ushort reliableId)
+        protected void InvokeDataReceived(MessageReader msg, SendOption sendOption, ushort reliableId)
         {
             DataReceivedEventArgs args = DataReceivedEventArgs.GetObject();
-            args.Set(bytes, sendOption, reliableId);
+            args.Set(msg, sendOption, reliableId);
 
             //Make a copy to avoid race condition between null check and invocation
             EventHandler<DataReceivedEventArgs> handler = DataReceived;
index 5aaf6d74103e98c0bedeb2f74fff58e93a41b3f7..eadf2b129fde01acd3461105969911361293c24e 100644 (file)
@@ -68,17 +68,17 @@ namespace Hazel
         /// <summary>
         ///     Invokes the NewConnection event with the supplied connection.
         /// </summary>
-        /// <param name="bytes">The user sent bytes that were received as part of the handshake.</param>
+        /// <param name="msg">The user sent bytes that were received as part of the handshake.</param>
         /// <param name="connection">The connection to pass in the arguments.</param>
         /// <remarks>
         ///     Implementers should call this to invoke the <see cref="NewConnection"/> event before data is received so that
         ///     subscribers do not miss any data that may have been sent immediately after connecting.
         /// </remarks>
-        protected void InvokeNewConnection(byte[] bytes, Connection connection)
+        protected void InvokeNewConnection(MessageReader msg, Connection connection)
         {
             //Get new args
             NewConnectionEventArgs args = NewConnectionEventArgs.GetObject();
-            args.Set(bytes, connection);
+            args.Set(msg, connection);
 
             //Make a copy to avoid race condition between null check and invocation
             EventHandler<NewConnectionEventArgs> handler = NewConnection;
index ffdcce05082d0ea1cca413c5e088517fe14e5720..69446e40193939b855655abf79f25c32b3910347 100644 (file)
@@ -35,7 +35,7 @@ namespace Hazel
         /// <summary>
         ///     The bytes received from the client.
         /// </summary>
-        public byte[] Bytes { get; private set; }
+        public MessageReader Message { get; private set; }
 
         /// <summary>
         ///     The <see cref="SendOption"/> the data was sent with.
@@ -57,9 +57,9 @@ namespace Hazel
         /// </summary>
         /// <param name="bytes">The bytes received.</param>
         /// <param name="sendOption">The send option used to send the data.</param>
-        internal void Set(byte[] bytes, SendOption sendOption, ushort reliableId)
+        internal void Set(MessageReader msg, SendOption sendOption, ushort reliableId)
         {
-            this.Bytes = bytes;
+            this.Message = msg;
             this.SendOption = sendOption;
             this.ReliableId = reliableId;
         }
index 49e2e6464422ec98dd6166c2f55a0dcbdba97193..f6951b3f99f81031f7696e8f8f1dc99dc873ea82 100644 (file)
@@ -29,14 +29,13 @@ namespace Hazel
 
         private int readHead;
         
-        public static MessageReader Get(MessageReader srcMsg)
+        public static MessageReader GetRaw(byte[] bytes, int offset, int length)
         {
             var output = ReaderPool.GetObject();
-            output.Buffer = srcMsg.Buffer;
-            output.Offset = srcMsg.Offset;
-            output.Position = srcMsg.Position;
-            output.Length = srcMsg.Length;
-            output.Tag = srcMsg.Tag;
+            output.Buffer = bytes;
+            output.Offset = offset;
+            output.Position = 0;
+            output.Length = length;
             return output;
         }
 
index f6e911db837b4520f586233a8001be9cb74b33a8..b757284f2deeace2c332625d2ae1b191eabf27f7 100644 (file)
@@ -35,7 +35,7 @@ namespace Hazel
         /// <summary>
         ///     The data received from the client in the handshake.
         /// </summary>
-        public byte[] HandshakeData { get; private set; }
+        public MessageReader HandshakeData { get; private set; }
 
         /// <summary>
         ///     The <see cref="Connection"/> to the new client.
@@ -53,11 +53,11 @@ namespace Hazel
         /// <summary>
         ///     Sets the members of the arguments.
         /// </summary>
-        /// <param name="bytes">The bytes that were received in the handshake.</param>
+        /// <param name="msg">The bytes that were received in the handshake.</param>
         /// <param name="connection">The new connection</param>
-        internal void Set(byte[] bytes, Connection connection)
+        internal void Set(MessageReader msg, Connection connection)
         {
-            this.HandshakeData = bytes;
+            this.HandshakeData = msg;
             this.Connection = connection;
         }
 
index bf3b49da796da4f4fb7706db18af88c14a47f3c7..9e525b224efe0e24e4e0c1b4b5279f8e528f73bb 100644 (file)
@@ -165,7 +165,15 @@ namespace Hazel.Udp
                 ptr += fragment.data.Length - fragment.offset;
             }
 
-            InvokeDataReceived(completeData, SendOption.FragmentedReliable, 0);
+            var reader = MessageReader.GetRaw(completeData, 0, completeData.Length);
+            try
+            {
+                InvokeDataReceived(reader, SendOption.FragmentedReliable, 0);
+            }
+            finally
+            {
+                reader.Recycle();
+            }
         }
 
         /// <summary>
index 16a85d950eb1d014ba11ca3e9e623195c80af2c7..926a61683be552b647722fed389075b8a9ddd78b 100644 (file)
@@ -242,10 +242,15 @@ namespace Hazel.Udp
         /// <param name="dataOffset">The offset of data in the buffer.</param>
         void InvokeDataReceived(SendOption sendOption, byte[] buffer, int dataOffset, ushort reliableId)
         {
-            byte[] dataBytes = new byte[buffer.Length - dataOffset];
-            Buffer.BlockCopy(buffer, dataOffset, dataBytes, 0, dataBytes.Length);
-            
-            InvokeDataReceived(dataBytes, sendOption, reliableId);
+            var reader = MessageReader.GetRaw(buffer, dataOffset, buffer.Length - dataOffset);
+            try
+            {
+                InvokeDataReceived(reader, sendOption, reliableId);
+            }
+            finally
+            {
+                reader.Recycle();
+            }
         }
 
         /// <summary>
index 44410d2fbeee30871a0249ebfc9ebaf959db94e0..c8f5333a647c9be4b075479b0d92c59e579bc3ea 100644 (file)
@@ -153,14 +153,9 @@ namespace Hazel.Udp
             UdpServerConnection connection;
             lock (connections)
             {
-                aware = connections.ContainsKey(remoteEndPoint);
-
                 //If we're aware of this connection use the one already
-                if (aware)
-                    connection = connections[remoteEndPoint];
-                
                 //If this is a new client then connect with them!
-                else
+                if (!(aware = connections.TryGetValue(remoteEndPoint, out connection)))
                 {
                     //Check for malformed connection attempts
                     if (buffer[0] != (byte)UdpSendOption.Hello)
@@ -177,9 +172,15 @@ namespace Hazel.Udp
             //If it's a new connection invoke the NewConnection event.
             if (!aware)
             {
-                byte[] dataBuffer = new byte[buffer.Length - 3];
-                Buffer.BlockCopy(buffer, 3, dataBuffer, 0, buffer.Length - 3);
-                InvokeNewConnection(dataBuffer, connection);
+                var reader = MessageReader.GetRaw(buffer, 4, buffer.Length - 4);
+                try
+                {
+                    InvokeNewConnection(reader, connection);
+                }
+                finally
+                {
+                    reader.Recycle();
+                }
             }
         }