diff --git a/.editorconfig b/.editorconfig
index ef1bbd10..cade6374 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -188,7 +188,6 @@ csharp_style_unused_value_assignment_preference = discard_variable:suggestion
dotnet_diagnostic.IDE0059.severity = suggestion
dotnet_diagnostic.IDE0002.severity = none
dotnet_diagnostic.IDE0010.severity = none
-dotnet_diagnostic.IDE0021.severity = none
dotnet_diagnostic.IDE0028.severity = none
dotnet_diagnostic.IDE0049.severity = none
dotnet_diagnostic.IDE0053.severity = none
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 27ca2a33..153513e2 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,6 +1,7 @@
{
"version": "0.2.0",
"configurations": [
+
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index a535c974..81c1eb4d 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,41 +1,55 @@
{
"version": "2.0.0",
"tasks": [
- {
- "label": "build",
- "command": "dotnet",
- "type": "process",
- "args": [
- "build",
- "${workspaceFolder}/Tests/HiveMQtt.Test/HiveMQtt.Test.csproj",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary"
- ],
- "problemMatcher": "$msCompile"
- },
- {
- "label": "publish",
- "command": "dotnet",
- "type": "process",
- "args": [
- "publish",
- "${workspaceFolder}/Tests/HiveMQtt.Test/HiveMQtt.Test.csproj",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary"
- ],
- "problemMatcher": "$msCompile"
- },
- {
- "label": "watch",
- "command": "dotnet",
- "type": "process",
- "args": [
- "watch",
- "run",
- "--project",
- "${workspaceFolder}/Tests/HiveMQtt.Test/HiveMQtt.Test.csproj"
- ],
- "problemMatcher": "$msCompile"
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/Tests/HiveMQtt.Test/HiveMQtt.Test.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/Tests/HiveMQtt.Test/HiveMQtt.Test.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "--project",
+ "${workspaceFolder}/Tests/HiveMQtt.Test/HiveMQtt.Test.csproj"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "build ClientBenchmarkApp",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/Benchmarks/ClientBenchmarkApp/ClientBenchmarkApp.csproj"
+ ],
+ "problemMatcher": "$msCompile",
+ "group": {
+ "kind": "build",
+ "isDefault": true
}
+ }
]
-}
\ No newline at end of file
+}
diff --git a/Benchmarks/ClientBenchmarkApp/ClientBenchmark.cs b/Benchmarks/ClientBenchmarkApp/ClientBenchmark.cs
new file mode 100644
index 00000000..a55af0f6
--- /dev/null
+++ b/Benchmarks/ClientBenchmarkApp/ClientBenchmark.cs
@@ -0,0 +1,71 @@
+namespace ClientBenchmarkApp;
+
+using System;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Running;
+using BenchmarkDotNet.Jobs;
+using BenchmarkDotNet.Engines;
+
+using HiveMQtt.Client;
+using HiveMQtt.Client.Options;
+using HiveMQtt.MQTT5;
+using HiveMQtt.MQTT5.ReasonCodes;
+using HiveMQtt.MQTT5.Types;
+
+[SimpleJob(RunStrategy.Monitoring, iterationCount: 10, id: "MonitoringJob")]
+public class ClientBenchmarks : IDisposable
+{
+ private readonly string smallPayload = new string(/*lang=json,strict*/ "{\"interference\": \"1029384\"}");
+
+ private HiveMQClient client;
+
+ [GlobalSetup]
+ public async Task SetupAsync()
+ {
+ var options = new HiveMQClientOptions
+ {
+ Host = "127.0.0.1",
+ Port = 1883,
+ };
+
+ this.client = new HiveMQClient(options);
+ Console.WriteLine($"Connecting to {options.Host} on port {options.Port}...");
+ await this.client.ConnectAsync().ConfigureAwait(false);
+
+ if (this.client.IsConnected())
+ {
+ Console.WriteLine("HiveMQ client connected.");
+ }
+ else
+ {
+ Console.WriteLine("Client failed to connect!");
+ }
+ }
+
+ [GlobalCleanup]
+ public async Task CleanUpAsync()
+ {
+ Console.WriteLine("Disconnecting from HiveMQ...");
+ await this.client.DisconnectAsync().ConfigureAwait(false);
+ }
+
+ [Benchmark(Description = "Publish a QoS 0 messages to the broker.")]
+ public async Task PublishQoS0MessageAsync()
+ {
+ await this.client.PublishAsync("benchmarks/PublishQoS0Messages", this.smallPayload).ConfigureAwait(false);
+ }
+
+ [Benchmark(Description = "Publish a QoS 1 messages to the broker.")]
+ public async Task PublishQoS1MessageAsync()
+ {
+ await this.client.PublishAsync("benchmarks/PublishQoS1Messages", this.smallPayload, QualityOfService.AtLeastOnceDelivery).ConfigureAwait(false);
+ }
+
+ [Benchmark(Description = "Publish a QoS 2 messages to the broker.")]
+ public async Task PublishQoS2MessageAsync()
+ {
+ await this.client.PublishAsync("benchmarks/PublishQoS1Messages", this.smallPayload, QualityOfService.ExactlyOnceDelivery).ConfigureAwait(false);
+ }
+
+ public void Dispose() => GC.SuppressFinalize(this);
+}
diff --git a/Benchmarks/ClientBenchmarkApp/ClientBenchmarkApp.csproj b/Benchmarks/ClientBenchmarkApp/ClientBenchmarkApp.csproj
new file mode 100644
index 00000000..8e50f7b4
--- /dev/null
+++ b/Benchmarks/ClientBenchmarkApp/ClientBenchmarkApp.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/Benchmarks/ClientBenchmarkApp/Program.cs b/Benchmarks/ClientBenchmarkApp/Program.cs
new file mode 100644
index 00000000..24f91f89
--- /dev/null
+++ b/Benchmarks/ClientBenchmarkApp/Program.cs
@@ -0,0 +1,11 @@
+namespace ClientBenchmarkApp;
+
+using System;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Running;
+
+public class Program
+{
+ public static void Main(string[] args)
+ => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
+}
diff --git a/Benchmarks/ClientBenchmarkApp/README.md b/Benchmarks/ClientBenchmarkApp/README.md
new file mode 100644
index 00000000..99b5e89b
--- /dev/null
+++ b/Benchmarks/ClientBenchmarkApp/README.md
@@ -0,0 +1,5 @@
+# Benchmarks
+
+The benchmarks are built with [BenchmarkDotNet](https://benchmarkdotnet.org) and can be run with:
+
+`dotnet run ClientBenchmarkApp.csproj -c Release`
diff --git a/Source/HiveMQtt/Client/HiveMQClientTrafficProcessor.cs b/Source/HiveMQtt/Client/HiveMQClientTrafficProcessor.cs
index b59a3f12..233ec5dd 100644
--- a/Source/HiveMQtt/Client/HiveMQClientTrafficProcessor.cs
+++ b/Source/HiveMQtt/Client/HiveMQClientTrafficProcessor.cs
@@ -46,7 +46,6 @@ private Task TrafficOutflowProcessorAsync(CancellationToken cancellationTo
{
var stopWatch = new Stopwatch();
var keepAlivePeriod = this.Options.KeepAlive / 2;
- TimeSpan elapsed;
stopWatch.Start();
@@ -54,9 +53,7 @@ private Task TrafficOutflowProcessorAsync(CancellationToken cancellationTo
while (this.connectState != ConnectState.Disconnected)
{
- elapsed = stopWatch.Elapsed;
-
- if (elapsed > TimeSpan.FromSeconds(keepAlivePeriod))
+ if (stopWatch.Elapsed > TimeSpan.FromSeconds(keepAlivePeriod))
{
// Send PingReq
Logger.Trace("--> PingReq");
@@ -80,7 +77,7 @@ private Task TrafficOutflowProcessorAsync(CancellationToken cancellationTo
Logger.Trace($"TrafficOutflowProcessor: {this.sendQueue.Count} packets waiting to be sent.");
- // Batch load up to 20 queued packets
+ // Batch load up to 50 queued packets
List packetsToSend = new();
while (this.sendQueue.TryDequeue(out var p))
{
diff --git a/Source/HiveMQtt/Client/HiveMQClientUtil.cs b/Source/HiveMQtt/Client/HiveMQClientUtil.cs
index 18993be5..c69646c6 100644
--- a/Source/HiveMQtt/Client/HiveMQClientUtil.cs
+++ b/Source/HiveMQtt/Client/HiveMQClientUtil.cs
@@ -99,7 +99,7 @@ public static bool MatchTopic(string pattern, string candidate)
if (pattern == "+")
{
- // A subscription to “+” will not receive any messages published to a topic containing a $
+ // A subscription to “+” will not receive any messages published to a topic beginning with a $ or /
if (candidate.StartsWith("$", System.StringComparison.CurrentCulture) ||
candidate.StartsWith("/", System.StringComparison.CurrentCulture))
{
diff --git a/Source/HiveMQtt/Client/PublishMessageBuilder.cs b/Source/HiveMQtt/Client/PublishMessageBuilder.cs
index 58f7214c..979bcd85 100644
--- a/Source/HiveMQtt/Client/PublishMessageBuilder.cs
+++ b/Source/HiveMQtt/Client/PublishMessageBuilder.cs
@@ -25,10 +25,7 @@ public class PublishMessageBuilder
///
private readonly MQTT5PublishMessage message;
- public PublishMessageBuilder()
- {
- this.message = new MQTT5PublishMessage();
- }
+ public PublishMessageBuilder() => this.message = new MQTT5PublishMessage();
///
/// Sets the payload of the publish message.
diff --git a/Source/HiveMQtt/Client/Results/UnsubscribeResult.cs b/Source/HiveMQtt/Client/Results/UnsubscribeResult.cs
index 57a23a01..fa6eddd3 100644
--- a/Source/HiveMQtt/Client/Results/UnsubscribeResult.cs
+++ b/Source/HiveMQtt/Client/Results/UnsubscribeResult.cs
@@ -19,10 +19,7 @@ namespace HiveMQtt.Client.Results;
public class UnsubscribeResult
{
- public UnsubscribeResult()
- {
- this.Subscriptions = new List();
- }
+ public UnsubscribeResult() => this.Subscriptions = new List();
public List Subscriptions { get; set; }
}
diff --git a/Source/HiveMQtt/Client/SubscribeOptionsBuilder.cs b/Source/HiveMQtt/Client/SubscribeOptionsBuilder.cs
index b921cfcd..ec3bb65f 100644
--- a/Source/HiveMQtt/Client/SubscribeOptionsBuilder.cs
+++ b/Source/HiveMQtt/Client/SubscribeOptionsBuilder.cs
@@ -23,10 +23,7 @@ public class SubscribeOptionsBuilder
{
private readonly SubscribeOptions options;
- public SubscribeOptionsBuilder()
- {
- this.options = new SubscribeOptions();
- }
+ public SubscribeOptionsBuilder() => this.options = new SubscribeOptions();
///
/// Adds a subscription to the list of subscriptions to be sent in the subscribe call.
diff --git a/Source/HiveMQtt/Client/UnsubscribeOptionsBuilder.cs b/Source/HiveMQtt/Client/UnsubscribeOptionsBuilder.cs
index 4a97f885..ee7db7cc 100644
--- a/Source/HiveMQtt/Client/UnsubscribeOptionsBuilder.cs
+++ b/Source/HiveMQtt/Client/UnsubscribeOptionsBuilder.cs
@@ -22,10 +22,7 @@ public class UnsubscribeOptionsBuilder
{
private readonly UnsubscribeOptions options;
- public UnsubscribeOptionsBuilder()
- {
- this.options = new UnsubscribeOptions();
- }
+ public UnsubscribeOptionsBuilder() => this.options = new UnsubscribeOptions();
///
/// Adds a single subscription to the UnsubscribeOption.