You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

220 lines
7.3 KiB

  1. using MQTTnet.Core;
  2. using MQTTnet.Core.Client;
  3. using MQTTnet.Core.Packets;
  4. using MQTTnet.Core.Protocol;
  5. using MQTTnet.Core.Server;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Diagnostics;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. namespace MQTTnet.TestApp.NetCore
  14. {
  15. public static class PerformanceTest
  16. {
  17. public static async Task RunAsync()
  18. {
  19. var server = Task.Factory.StartNew(RunServerAsync, TaskCreationOptions.LongRunning);
  20. var client = Task.Factory.StartNew(() => RunClientAsync(2000, TimeSpan.FromMilliseconds(10)), TaskCreationOptions.LongRunning);
  21. await Task.WhenAll(server, client).ConfigureAwait(false);
  22. }
  23. private static Task RunClientsAsync(int msgChunkSize, TimeSpan interval)
  24. {
  25. return Task.WhenAll(Enumerable.Range(0, 3).Select(i => Task.Run(() => RunClientAsync(msgChunkSize, interval))));
  26. }
  27. private static async Task RunClientAsync(int msgChunkSize, TimeSpan interval)
  28. {
  29. try
  30. {
  31. var options = new MqttClientTcpOptions
  32. {
  33. Server = "localhost",
  34. ClientId = "XYZ",
  35. CleanSession = true,
  36. DefaultCommunicationTimeout = TimeSpan.FromMinutes(10)
  37. };
  38. var client = new MqttClientFactory().CreateMqttClient();
  39. client.ApplicationMessageReceived += (s, e) =>
  40. {
  41. };
  42. client.Connected += async (s, e) =>
  43. {
  44. Console.WriteLine("### CONNECTED WITH SERVER ###");
  45. await client.SubscribeAsync(new List<TopicFilter>
  46. {
  47. new TopicFilter("#", MqttQualityOfServiceLevel.AtMostOnce)
  48. });
  49. Console.WriteLine("### SUBSCRIBED ###");
  50. };
  51. client.Disconnected += async (s, e) =>
  52. {
  53. Console.WriteLine("### DISCONNECTED FROM SERVER ###");
  54. await Task.Delay(TimeSpan.FromSeconds(5));
  55. try
  56. {
  57. await client.ConnectAsync(options);
  58. }
  59. catch
  60. {
  61. Console.WriteLine("### RECONNECTING FAILED ###");
  62. }
  63. };
  64. try
  65. {
  66. await client.ConnectAsync(options);
  67. }
  68. catch (Exception exception)
  69. {
  70. Console.WriteLine("### CONNECTING FAILED ###" + Environment.NewLine + exception);
  71. }
  72. Console.WriteLine("### WAITING FOR APPLICATION MESSAGES ###");
  73. var testMessageCount = 10000;
  74. var message = CreateMessage();
  75. var stopwatch = Stopwatch.StartNew();
  76. for (var i = 0; i < testMessageCount; i++)
  77. {
  78. await client.PublishAsync(message);
  79. }
  80. stopwatch.Stop();
  81. Console.WriteLine($"Sent 10.000 messages within {stopwatch.ElapsedMilliseconds} ms ({stopwatch.ElapsedMilliseconds / (float)testMessageCount} ms / message).");
  82. stopwatch.Restart();
  83. var sentMessagesCount = 0;
  84. while (stopwatch.ElapsedMilliseconds < 1000)
  85. {
  86. await client.PublishAsync(message);
  87. sentMessagesCount++;
  88. }
  89. Console.WriteLine($"Sending {sentMessagesCount} messages per second.");
  90. var last = DateTime.Now;
  91. var msgCount = 0;
  92. while (true)
  93. {
  94. var msgs = Enumerable.Range(0, msgChunkSize)
  95. .Select(i => CreateMessage())
  96. .ToList();
  97. if (true)
  98. {
  99. //send concurrent (test for raceconditions)
  100. var sendTasks = msgs
  101. .Select(msg => PublishSingleMessage(client, msg, ref msgCount))
  102. .ToList();
  103. await Task.WhenAll(sendTasks);
  104. }
  105. else
  106. {
  107. await client.PublishAsync(msgs);
  108. msgCount += msgs.Count;
  109. //send multiple
  110. }
  111. var now = DateTime.Now;
  112. if (last < now - TimeSpan.FromSeconds(1))
  113. {
  114. Console.WriteLine($"sending {msgCount} intended {msgChunkSize / interval.TotalSeconds}");
  115. msgCount = 0;
  116. last = now;
  117. }
  118. await Task.Delay(interval).ConfigureAwait(false);
  119. }
  120. }
  121. catch (Exception exception)
  122. {
  123. Console.WriteLine(exception);
  124. }
  125. }
  126. private static MqttApplicationMessage CreateMessage()
  127. {
  128. return new MqttApplicationMessage(
  129. "A/B/C",
  130. Encoding.UTF8.GetBytes("Hello World"),
  131. MqttQualityOfServiceLevel.AtMostOnce,
  132. false
  133. );
  134. }
  135. private static Task PublishSingleMessage(IMqttClient client, MqttApplicationMessage applicationMessage, ref int count)
  136. {
  137. Interlocked.Increment(ref count);
  138. return Task.Run(() =>
  139. {
  140. return client.PublishAsync(applicationMessage);
  141. });
  142. }
  143. private static async Task RunServerAsync()
  144. {
  145. try
  146. {
  147. var options = new MqttServerOptions
  148. {
  149. ConnectionValidator = p =>
  150. {
  151. if (p.ClientId == "SpecialClient")
  152. {
  153. if (p.Username != "USER" || p.Password != "PASS")
  154. {
  155. return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
  156. }
  157. }
  158. return MqttConnectReturnCode.ConnectionAccepted;
  159. },
  160. DefaultCommunicationTimeout = TimeSpan.FromMinutes(10)
  161. };
  162. var mqttServer = new MqttServerFactory().CreateMqttServer(options);
  163. var msgs = 0;
  164. var stopwatch = Stopwatch.StartNew();
  165. mqttServer.ApplicationMessageReceived += (sender, args) =>
  166. {
  167. msgs++;
  168. if (stopwatch.ElapsedMilliseconds > 1000)
  169. {
  170. Console.WriteLine($"received {msgs}");
  171. msgs = 0;
  172. stopwatch.Restart();
  173. }
  174. };
  175. await mqttServer.StartAsync();
  176. Console.WriteLine("Press any key to exit.");
  177. Console.ReadLine();
  178. await mqttServer.StopAsync();
  179. }
  180. catch (Exception e)
  181. {
  182. Console.WriteLine(e);
  183. }
  184. Console.ReadLine();
  185. }
  186. }
  187. }