From 683bb43486699f1c8f4fda359711e00a2eed582f Mon Sep 17 00:00:00 2001 From: Christian Kratky Date: Thu, 14 May 2020 00:05:52 +0200 Subject: [PATCH] Fix performance issue in logger. --- .editorconfig | 5 +++++ Build/MQTTnet.nuspec | 1 + MQTTnet.sln | 1 + .../MQTTnet.Extensions.ManagedClient.csproj | 2 +- .../MQTTnet.Extensions.Rpc.csproj | 2 +- .../MQTTnet.Extensions.WebSocket4Net.csproj | 2 +- Source/MQTTnet/Adapter/MqttChannelAdapter.cs | 8 ++++---- .../Options/MqttClientOptionsBuilder.cs | 3 +++ Source/MQTTnet/Diagnostics/MqttNetLogger.cs | 20 ++++++++----------- .../MQTTnet/Implementations/MqttTcpChannel.cs | 14 ++++++++++--- Source/MQTTnet/MQTTnet.csproj | 4 ++-- .../Configurations/AllowNonOptimized.cs | 4 ++-- .../Configurations/BaseConfig.cs | 6 +++--- .../Configurations/RuntimeCompareConfig.cs | 4 ++-- .../MQTTnet.Core.Tests/Mockups/TestLogger.cs | 10 +++------- .../JsonServerStorage.cs | 10 +++++----- .../MQTTnet.TestApp.UniversalWindows.csproj | 3 +++ 17 files changed, 56 insertions(+), 43 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6555efd --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +[*.cs] + + +# CA1031: Do not catch general exception types +dotnet_diagnostic.CA1031.severity = none diff --git a/Build/MQTTnet.nuspec b/Build/MQTTnet.nuspec index 2e0c2e3..a149cc5 100644 --- a/Build/MQTTnet.nuspec +++ b/Build/MQTTnet.nuspec @@ -15,6 +15,7 @@ * [Core] Renamed some topic filter relevant classes (BREAKING CHANGE!). * [Core] Improved task management for UWP connections (thanks to @xgstation). * [Core] Fixed broken logger which decreases overall performance. +* [Core] Fixed issue in closed socket detection (fixes high CPU load issue). * [Client] Added method to trigger PING/PONG manually (connection check etc.). * [Client] Added support for certificate validation callback when using Web Sockets (requires netstandard2.1+). * [Client] Fixed a memory leak when web socket based connections trying to reconnect with an offline server. diff --git a/MQTTnet.sln b/MQTTnet.sln index 12ed09f..dd8c524 100644 --- a/MQTTnet.sln +++ b/MQTTnet.sln @@ -27,6 +27,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B3F60ECB-45BA-4C66-8903-8BB89CA67998}" ProjectSection(SolutionItems) = preProject .bettercodehub.yml = .bettercodehub.yml + .editorconfig = .editorconfig appveyor.yml = appveyor.yml LICENSE = LICENSE README.md = README.md diff --git a/Source/MQTTnet.Extensions.ManagedClient/MQTTnet.Extensions.ManagedClient.csproj b/Source/MQTTnet.Extensions.ManagedClient/MQTTnet.Extensions.ManagedClient.csproj index 01d7db9..c77de28 100644 --- a/Source/MQTTnet.Extensions.ManagedClient/MQTTnet.Extensions.ManagedClient.csproj +++ b/Source/MQTTnet.Extensions.ManagedClient/MQTTnet.Extensions.ManagedClient.csproj @@ -14,7 +14,7 @@ false UAP,Version=v10.0 UAP - 10.0.17134.0 + 10.0.18362.0 10.0.10240.0 .NETCore v5.0 diff --git a/Source/MQTTnet.Extensions.Rpc/MQTTnet.Extensions.Rpc.csproj b/Source/MQTTnet.Extensions.Rpc/MQTTnet.Extensions.Rpc.csproj index 01d7db9..c77de28 100644 --- a/Source/MQTTnet.Extensions.Rpc/MQTTnet.Extensions.Rpc.csproj +++ b/Source/MQTTnet.Extensions.Rpc/MQTTnet.Extensions.Rpc.csproj @@ -14,7 +14,7 @@ false UAP,Version=v10.0 UAP - 10.0.17134.0 + 10.0.18362.0 10.0.10240.0 .NETCore v5.0 diff --git a/Source/MQTTnet.Extensions.WebSocket4Net/MQTTnet.Extensions.WebSocket4Net.csproj b/Source/MQTTnet.Extensions.WebSocket4Net/MQTTnet.Extensions.WebSocket4Net.csproj index cf7f3bc..74a335e 100644 --- a/Source/MQTTnet.Extensions.WebSocket4Net/MQTTnet.Extensions.WebSocket4Net.csproj +++ b/Source/MQTTnet.Extensions.WebSocket4Net/MQTTnet.Extensions.WebSocket4Net.csproj @@ -14,7 +14,7 @@ false UAP,Version=v10.0 UAP - 10.0.17134.0 + 10.0.18362.0 10.0.10240.0 .NETCore v5.0 diff --git a/Source/MQTTnet/Adapter/MqttChannelAdapter.cs b/Source/MQTTnet/Adapter/MqttChannelAdapter.cs index bb5ffa7..61f0646 100644 --- a/Source/MQTTnet/Adapter/MqttChannelAdapter.cs +++ b/Source/MQTTnet/Adapter/MqttChannelAdapter.cs @@ -16,8 +16,8 @@ namespace MQTTnet.Adapter { public sealed class MqttChannelAdapter : Disposable, IMqttChannelAdapter { - const uint ErrorOperationAborted = 0x800703E3; - const int ReadBufferSize = 4096; // TODO: Move buffer size to config + const uint _errorOperationAborted = 0x800703E3; + const int _readBufferSize = 4096; // TODO: Move buffer size to config readonly IMqttNetScopedLogger _logger; readonly IMqttChannel _channel; @@ -245,7 +245,7 @@ namespace MQTTnet.Adapter var body = new byte[fixedHeader.RemainingLength]; var bodyOffset = 0; - var chunkSize = Math.Min(ReadBufferSize, fixedHeader.RemainingLength); + var chunkSize = Math.Min(_readBufferSize, fixedHeader.RemainingLength); do { @@ -304,7 +304,7 @@ namespace MQTTnet.Adapter if (exception is COMException comException) { - if ((uint)comException.HResult == ErrorOperationAborted) + if ((uint)comException.HResult == _errorOperationAborted) { throw new OperationCanceledException(); } diff --git a/Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs b/Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs index 4902fd0..b450adc 100644 --- a/Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs +++ b/Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs @@ -277,7 +277,10 @@ namespace MQTTnet.Client.Options #else Certificates = _tlsParameters.Certificates?.ToList(), #endif +#pragma warning disable CS0618 // Type or member is obsolete CertificateValidationCallback = _tlsParameters.CertificateValidationCallback, +#pragma warning restore CS0618 // Type or member is obsolete + CertificateValidationHandler = _tlsParameters.CertificateValidationHandler, IgnoreCertificateChainErrors = _tlsParameters.IgnoreCertificateChainErrors, IgnoreCertificateRevocationErrors = _tlsParameters.IgnoreCertificateRevocationErrors diff --git a/Source/MQTTnet/Diagnostics/MqttNetLogger.cs b/Source/MQTTnet/Diagnostics/MqttNetLogger.cs index 1428de5..7cc99e0 100644 --- a/Source/MQTTnet/Diagnostics/MqttNetLogger.cs +++ b/Source/MQTTnet/Diagnostics/MqttNetLogger.cs @@ -5,8 +5,7 @@ namespace MQTTnet.Diagnostics public class MqttNetLogger : IMqttNetLogger { readonly string _logId; - readonly string _source; - + public MqttNetLogger() { } @@ -37,23 +36,20 @@ namespace MQTTnet.Diagnostics return; } - if (parameters?.Length > 0) + try + { + message = string.Format(message ?? string.Empty, parameters); + } + catch (FormatException) { - try - { - message = string.Format(message, parameters); - } - catch - { - message = "MESSAGE FORMAT INVALID: " + message; - } + message = "MESSAGE FORMAT INVALID: " + message; } var logMessage = new MqttNetLogMessage { LogId = _logId, Timestamp = DateTime.UtcNow, - Source = _source, + Source = source, ThreadId = Environment.CurrentManagedThreadId, Level = level, Message = message, diff --git a/Source/MQTTnet/Implementations/MqttTcpChannel.cs b/Source/MQTTnet/Implementations/MqttTcpChannel.cs index 425f9e7..5f95e72 100644 --- a/Source/MQTTnet/Implementations/MqttTcpChannel.cs +++ b/Source/MQTTnet/Implementations/MqttTcpChannel.cs @@ -85,7 +85,12 @@ namespace MQTTnet.Implementations } catch { +#if NETSTANDARD2_1 + await sslStream.DisposeAsync().ConfigureAwait(false); +#else sslStream.Dispose(); +#endif + throw; } @@ -127,7 +132,8 @@ namespace MQTTnet.Implementations } catch (ObjectDisposedException) { - return -1; + // Indicate a graceful socket close. + return 0; } catch (IOException exception) { @@ -190,15 +196,17 @@ namespace MQTTnet.Implementations bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { - #region OBSOLETE +#region OBSOLETE +#pragma warning disable CS0618 // Type or member is obsolete var certificateValidationCallback = _options?.TlsOptions?.CertificateValidationCallback; +#pragma warning restore CS0618 // Type or member is obsolete if (certificateValidationCallback != null) { return certificateValidationCallback(x509Certificate, chain, sslPolicyErrors, _clientOptions); } - #endregion +#endregion var certificateValidationHandler = _options?.TlsOptions?.CertificateValidationHandler; if (certificateValidationHandler != null) diff --git a/Source/MQTTnet/MQTTnet.csproj b/Source/MQTTnet/MQTTnet.csproj index f6f52d6..4f61931 100644 --- a/Source/MQTTnet/MQTTnet.csproj +++ b/Source/MQTTnet/MQTTnet.csproj @@ -20,8 +20,8 @@ false UAP,Version=v10.0 UAP - 10.0.17134.0 - 10.0.10586.212 + 10.0.18362.0 + 10.0.10240.0 .NETCore v5.0 $(DefineConstants);WINDOWS_UWP diff --git a/Tests/MQTTnet.Benchmarks/Configurations/AllowNonOptimized.cs b/Tests/MQTTnet.Benchmarks/Configurations/AllowNonOptimized.cs index 076d1e8..248c52f 100644 --- a/Tests/MQTTnet.Benchmarks/Configurations/AllowNonOptimized.cs +++ b/Tests/MQTTnet.Benchmarks/Configurations/AllowNonOptimized.cs @@ -13,8 +13,8 @@ namespace MQTTnet.Benchmarks.Configurations { public AllowNonOptimized() { - Add(JitOptimizationsValidator.DontFailOnError); // ALLOW NON-OPTIMIZED DLLS - Add(Job.InProcess); + AddValidator(JitOptimizationsValidator.DontFailOnError); // ALLOW NON-OPTIMIZED DLLS + AddJob(Job.InProcess); } } } \ No newline at end of file diff --git a/Tests/MQTTnet.Benchmarks/Configurations/BaseConfig.cs b/Tests/MQTTnet.Benchmarks/Configurations/BaseConfig.cs index 418bb2f..ff5b148 100644 --- a/Tests/MQTTnet.Benchmarks/Configurations/BaseConfig.cs +++ b/Tests/MQTTnet.Benchmarks/Configurations/BaseConfig.cs @@ -7,9 +7,9 @@ namespace MQTTnet.Benchmarks.Configurations { public BaseConfig() { - Add(DefaultConfig.Instance.GetLoggers().ToArray()); // manual config has no loggers by default - Add(DefaultConfig.Instance.GetExporters().ToArray()); // manual config has no exporters by default - Add(DefaultConfig.Instance.GetColumnProviders().ToArray()); // manual config has no columns by default + AddLogger(DefaultConfig.Instance.GetLoggers().ToArray()); // manual config has no loggers by default + AddExporter(DefaultConfig.Instance.GetExporters().ToArray()); // manual config has no exporters by default + AddColumnProvider(DefaultConfig.Instance.GetColumnProviders().ToArray()); // manual config has no columns by default } } } diff --git a/Tests/MQTTnet.Benchmarks/Configurations/RuntimeCompareConfig.cs b/Tests/MQTTnet.Benchmarks/Configurations/RuntimeCompareConfig.cs index 5838424..60f009b 100644 --- a/Tests/MQTTnet.Benchmarks/Configurations/RuntimeCompareConfig.cs +++ b/Tests/MQTTnet.Benchmarks/Configurations/RuntimeCompareConfig.cs @@ -9,8 +9,8 @@ namespace MQTTnet.Benchmarks.Configurations { public RuntimeCompareConfig() { - Add(Job.Default.With(ClrRuntime.Net472)); - Add(Job.Default.With(CoreRuntime.Core22).With(CsProjCoreToolchain.NetCoreApp22)); + AddJob(Job.Default.WithRuntime(ClrRuntime.Net472)); + AddJob(Job.Default.WithRuntime(CoreRuntime.Core22).WithToolchain(CsProjCoreToolchain.NetCoreApp22)); } } diff --git a/Tests/MQTTnet.Core.Tests/Mockups/TestLogger.cs b/Tests/MQTTnet.Core.Tests/Mockups/TestLogger.cs index bfc1174..247c0f0 100644 --- a/Tests/MQTTnet.Core.Tests/Mockups/TestLogger.cs +++ b/Tests/MQTTnet.Core.Tests/Mockups/TestLogger.cs @@ -12,18 +12,14 @@ namespace MQTTnet.Tests.Mockups return new MqttNetScopedLogger(this, source); } - public void Publish(MqttNetLogLevel logLevel, string message, object[] parameters, Exception exception) + public void Publish(MqttNetLogLevel logLevel, string source, string message, object[] parameters, Exception exception) { LogMessagePublished?.Invoke(this, new MqttNetLogMessagePublishedEventArgs(new MqttNetLogMessage { Level = logLevel, - Message = message + Message = string.Format(message, parameters), + Exception = exception })); } - - public void Publish(MqttNetLogLevel logLevel, string source, string message, object[] parameters, Exception exception) - { - throw new NotImplementedException(); - } } } diff --git a/Tests/MQTTnet.TestApp.UniversalWindows/JsonServerStorage.cs b/Tests/MQTTnet.TestApp.UniversalWindows/JsonServerStorage.cs index fbf5b66..1c8434b 100644 --- a/Tests/MQTTnet.TestApp.UniversalWindows/JsonServerStorage.cs +++ b/Tests/MQTTnet.TestApp.UniversalWindows/JsonServerStorage.cs @@ -6,16 +6,16 @@ using Newtonsoft.Json; namespace MQTTnet.TestApp.UniversalWindows { - public class JsonServerStorage : IMqttServerStorage + public sealed class JsonServerStorage : IMqttServerStorage { - private readonly string _filename = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "Retained.json"); + readonly string _filename = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "Retained.json"); - public async Task SaveRetainedMessagesAsync(IList messages) + public Task SaveRetainedMessagesAsync(IList messages) { - await Task.CompletedTask; - var json = JsonConvert.SerializeObject(messages); File.WriteAllText(_filename, json); + + return Task.CompletedTask; } public async Task> LoadRetainedMessagesAsync() diff --git a/Tests/MQTTnet.TestApp.UniversalWindows/MQTTnet.TestApp.UniversalWindows.csproj b/Tests/MQTTnet.TestApp.UniversalWindows/MQTTnet.TestApp.UniversalWindows.csproj index f7e4223..3c8c989 100644 --- a/Tests/MQTTnet.TestApp.UniversalWindows/MQTTnet.TestApp.UniversalWindows.csproj +++ b/Tests/MQTTnet.TestApp.UniversalWindows/MQTTnet.TestApp.UniversalWindows.csproj @@ -105,6 +105,9 @@ Designer + + .editorconfig +