From e7a7bb1a7b349c0068e6837046885aa5ee1eca83 Mon Sep 17 00:00:00 2001 From: JanEggers Date: Thu, 10 May 2018 19:18:31 +0200 Subject: [PATCH 1/3] added benchmark for serializers --- .../MqttApplicationMessageExtensions.cs | 2 +- .../Internal}/TestMqttChannel.cs | 2 +- .../MQTTnet.Benchmarks.csproj | 1 + Tests/MQTTnet.Benchmarks/Program.cs | 20 ++++- .../MQTTnet.Benchmarks/SerializerBenchmark.cs | 75 +++++++++++++++++++ .../MqttPacketReaderTests.cs | 1 + 6 files changed, 98 insertions(+), 3 deletions(-) rename {Tests/MQTTnet.Core.Tests => Frameworks/MQTTnet.NetStandard/Internal}/TestMqttChannel.cs (96%) create mode 100644 Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs diff --git a/Frameworks/MQTTnet.NetStandard/Internal/MqttApplicationMessageExtensions.cs b/Frameworks/MQTTnet.NetStandard/Internal/MqttApplicationMessageExtensions.cs index b1d1a389..79eb2c43 100644 --- a/Frameworks/MQTTnet.NetStandard/Internal/MqttApplicationMessageExtensions.cs +++ b/Frameworks/MQTTnet.NetStandard/Internal/MqttApplicationMessageExtensions.cs @@ -2,7 +2,7 @@ namespace MQTTnet.Internal { - internal static class MqttApplicationMessageExtensions + public static class MqttApplicationMessageExtensions { public static MqttApplicationMessage ToApplicationMessage(this MqttPublishPacket publishPacket) { diff --git a/Tests/MQTTnet.Core.Tests/TestMqttChannel.cs b/Frameworks/MQTTnet.NetStandard/Internal/TestMqttChannel.cs similarity index 96% rename from Tests/MQTTnet.Core.Tests/TestMqttChannel.cs rename to Frameworks/MQTTnet.NetStandard/Internal/TestMqttChannel.cs index 2b4914b7..b380b085 100644 --- a/Tests/MQTTnet.Core.Tests/TestMqttChannel.cs +++ b/Frameworks/MQTTnet.NetStandard/Internal/TestMqttChannel.cs @@ -3,7 +3,7 @@ using System.Threading; using System.Threading.Tasks; using MQTTnet.Channel; -namespace MQTTnet.Core.Tests +namespace MQTTnet.Core.Internal { public class TestMqttChannel : IMqttChannel { diff --git a/Tests/MQTTnet.Benchmarks/MQTTnet.Benchmarks.csproj b/Tests/MQTTnet.Benchmarks/MQTTnet.Benchmarks.csproj index 49773119..3b52bbae 100644 --- a/Tests/MQTTnet.Benchmarks/MQTTnet.Benchmarks.csproj +++ b/Tests/MQTTnet.Benchmarks/MQTTnet.Benchmarks.csproj @@ -150,6 +150,7 @@ + diff --git a/Tests/MQTTnet.Benchmarks/Program.cs b/Tests/MQTTnet.Benchmarks/Program.cs index 965ddb55..ad2c3630 100644 --- a/Tests/MQTTnet.Benchmarks/Program.cs +++ b/Tests/MQTTnet.Benchmarks/Program.cs @@ -1,5 +1,7 @@ using System; +using System.Threading; using BenchmarkDotNet.Running; +using MQTTnet.Diagnostics; namespace MQTTnet.Benchmarks { @@ -7,7 +9,23 @@ namespace MQTTnet.Benchmarks { public static void Main(string[] args) { - var summary = BenchmarkRunner.Run(); + Console.WriteLine($"MQTTnet - BenchmarkApp.{TargetFrameworkInfoProvider.TargetFramework}"); + Console.WriteLine("1 = MessageProcessingBenchmark"); + Console.WriteLine("2 = SerializerBenchmark"); + + var pressedKey = Console.ReadKey(true); + switch (pressedKey.KeyChar) + { + case '1': + BenchmarkRunner.Run(); + break; + case '2': + BenchmarkRunner.Run(); + break; + default: + break; + } + Console.ReadLine(); } } diff --git a/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs b/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs new file mode 100644 index 00000000..d343eb14 --- /dev/null +++ b/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs @@ -0,0 +1,75 @@ +using BenchmarkDotNet.Attributes; +using MQTTnet.Client; +using MQTTnet.Packets; +using MQTTnet.Serializer; +using MQTTnet.Internal; +using MQTTnet.Server; +using BenchmarkDotNet.Attributes.Jobs; +using BenchmarkDotNet.Attributes.Exporters; +using System; +using System.Threading; +using System.IO; +using MQTTnet.Core.Internal; + +namespace MQTTnet.Benchmarks +{ + [ClrJob] + [RPlotExporter] + [MemoryDiagnoser] + public class SerializerBenchmark + { + private MqttApplicationMessage _message; + private MqttBasePacket _packet; + private ArraySegment _serializedPacket; + private MqttPacketSerializer _serializer; + + [GlobalSetup] + public void Setup() + { + _message = new MqttApplicationMessageBuilder() + .WithTopic("A") + .Build(); + + _packet = _message.ToPublishPacket(); + _serializer = new MqttPacketSerializer(); + _serializedPacket = _serializer.Serialize(_packet); + } + + [Benchmark] + public void Serialize_10000_Messages() + { + for (var i = 0; i < 10000; i++) + { + _serializer.Serialize(_packet); + } + } + + [Benchmark] + public void Deserialize_10000_Messages() + { + for (var i = 0; i < 10000; i++) + { + using (var headerStream = new MemoryStream(Join(_serializedPacket))) + { + var header = MqttPacketReader.ReadHeaderAsync(new TestMqttChannel(headerStream), CancellationToken.None).GetAwaiter().GetResult(); + + using (var bodyStream = new MemoryStream(Join(_serializedPacket), (int)headerStream.Position, header.BodyLength)) + { + var deserializedPacket = _serializer.Deserialize(header, bodyStream); + } + } + } + } + + private static byte[] Join(params ArraySegment[] chunks) + { + var buffer = new MemoryStream(); + foreach (var chunk in chunks) + { + buffer.Write(chunk.Array, chunk.Offset, chunk.Count); + } + + return buffer.ToArray(); + } + } +} diff --git a/Tests/MQTTnet.Core.Tests/MqttPacketReaderTests.cs b/Tests/MQTTnet.Core.Tests/MqttPacketReaderTests.cs index ca48ad9b..72a675bf 100644 --- a/Tests/MQTTnet.Core.Tests/MqttPacketReaderTests.cs +++ b/Tests/MQTTnet.Core.Tests/MqttPacketReaderTests.cs @@ -1,6 +1,7 @@ using System.IO; using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; +using MQTTnet.Core.Internal; using MQTTnet.Serializer; namespace MQTTnet.Core.Tests From 17db90d5abfab790e36ef6c24d8b7e6d9e50ca53 Mon Sep 17 00:00:00 2001 From: JanEggers Date: Thu, 10 May 2018 19:25:33 +0200 Subject: [PATCH 2/3] fixed build --- Tests/MQTTnet.Core.Tests/ExtensionTests.cs | 12 ++++++------ .../MQTTnet.Core.Tests/MqttPacketSerializerTests.cs | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Tests/MQTTnet.Core.Tests/ExtensionTests.cs b/Tests/MQTTnet.Core.Tests/ExtensionTests.cs index daeea620..696cfa3c 100644 --- a/Tests/MQTTnet.Core.Tests/ExtensionTests.cs +++ b/Tests/MQTTnet.Core.Tests/ExtensionTests.cs @@ -14,20 +14,20 @@ namespace MQTTnet.Core.Tests [TestMethod] public async Task TimeoutAfter() { - await Internal.TaskExtensions.TimeoutAfter(ct => Task.Delay(TimeSpan.FromMilliseconds(500), ct), TimeSpan.FromMilliseconds(100), CancellationToken.None); + await MQTTnet.Internal.TaskExtensions.TimeoutAfter(ct => Task.Delay(TimeSpan.FromMilliseconds(500), ct), TimeSpan.FromMilliseconds(100), CancellationToken.None); } [ExpectedException(typeof(MqttCommunicationTimedOutException))] [TestMethod] public async Task TimeoutAfterWithResult() { - await Internal.TaskExtensions.TimeoutAfter(ct => Task.Delay(TimeSpan.FromMilliseconds(500), ct).ContinueWith(t => 5, ct), TimeSpan.FromMilliseconds(100), CancellationToken.None); + await MQTTnet.Internal.TaskExtensions.TimeoutAfter(ct => Task.Delay(TimeSpan.FromMilliseconds(500), ct).ContinueWith(t => 5, ct), TimeSpan.FromMilliseconds(100), CancellationToken.None); } [TestMethod] public async Task TimeoutAfterCompleteInTime() { - var result = await Internal.TaskExtensions.TimeoutAfter(ct => Task.Delay(TimeSpan.FromMilliseconds(100), ct).ContinueWith(t => 5, ct), TimeSpan.FromMilliseconds(500), CancellationToken.None); + var result = await MQTTnet.Internal.TaskExtensions.TimeoutAfter(ct => Task.Delay(TimeSpan.FromMilliseconds(100), ct).ContinueWith(t => 5, ct), TimeSpan.FromMilliseconds(500), CancellationToken.None); Assert.AreEqual(5, result); } @@ -36,7 +36,7 @@ namespace MQTTnet.Core.Tests { try { - await Internal.TaskExtensions.TimeoutAfter(ct => Task.Run(() => + await MQTTnet.Internal.TaskExtensions.TimeoutAfter(ct => Task.Run(() => { var iis = new int[0]; iis[1] = 0; @@ -55,7 +55,7 @@ namespace MQTTnet.Core.Tests { try { - await Internal.TaskExtensions.TimeoutAfter(ct => Task.Run(() => + await MQTTnet.Internal.TaskExtensions.TimeoutAfter(ct => Task.Run(() => { var iis = new int[0]; iis[1] = 0; @@ -76,7 +76,7 @@ namespace MQTTnet.Core.Tests var tasks = Enumerable.Range(0, 100000) .Select(i => { - return Internal.TaskExtensions.TimeoutAfter(ct => Task.Delay(TimeSpan.FromMilliseconds(1), ct), TimeSpan.FromMinutes(1), CancellationToken.None); + return MQTTnet.Internal.TaskExtensions.TimeoutAfter(ct => Task.Delay(TimeSpan.FromMilliseconds(1), ct), TimeSpan.FromMinutes(1), CancellationToken.None); }); await Task.WhenAll(tasks); diff --git a/Tests/MQTTnet.Core.Tests/MqttPacketSerializerTests.cs b/Tests/MQTTnet.Core.Tests/MqttPacketSerializerTests.cs index 580bc4d4..a45736d2 100644 --- a/Tests/MQTTnet.Core.Tests/MqttPacketSerializerTests.cs +++ b/Tests/MQTTnet.Core.Tests/MqttPacketSerializerTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Text; using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; +using MQTTnet.Core.Internal; using MQTTnet.Packets; using MQTTnet.Protocol; using MQTTnet.Serializer; From 97d91ec0f87cc52f0e523e7d2a857bdf2b8f62ab Mon Sep 17 00:00:00 2001 From: JanEggers Date: Thu, 10 May 2018 19:30:29 +0200 Subject: [PATCH 3/3] fixed code quality issues --- Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs b/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs index d343eb14..bcfff1c3 100644 --- a/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs +++ b/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs @@ -18,7 +18,6 @@ namespace MQTTnet.Benchmarks [MemoryDiagnoser] public class SerializerBenchmark { - private MqttApplicationMessage _message; private MqttBasePacket _packet; private ArraySegment _serializedPacket; private MqttPacketSerializer _serializer; @@ -26,11 +25,11 @@ namespace MQTTnet.Benchmarks [GlobalSetup] public void Setup() { - _message = new MqttApplicationMessageBuilder() + var message = new MqttApplicationMessageBuilder() .WithTopic("A") .Build(); - _packet = _message.ToPublishPacket(); + _packet = message.ToPublishPacket(); _serializer = new MqttPacketSerializer(); _serializedPacket = _serializer.Serialize(_packet); } @@ -55,7 +54,7 @@ namespace MQTTnet.Benchmarks using (var bodyStream = new MemoryStream(Join(_serializedPacket), (int)headerStream.Position, header.BodyLength)) { - var deserializedPacket = _serializer.Deserialize(header, bodyStream); + _serializer.Deserialize(header, bodyStream); } } }