-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Elide repeated Action-delegate allocation by caching it #1324
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,18 +18,24 @@ public sealed class MqttTcpChannel : IMqttChannel | |
{ | ||
readonly IMqttClientOptions _clientOptions; | ||
readonly MqttClientTcpOptions _tcpOptions; | ||
readonly Action _disposeAction; | ||
|
||
Stream _stream; | ||
|
||
public MqttTcpChannel(IMqttClientOptions clientOptions) | ||
public MqttTcpChannel() | ||
{ | ||
_disposeAction = Dispose; | ||
} | ||
|
||
public MqttTcpChannel(IMqttClientOptions clientOptions) : this() | ||
{ | ||
_clientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions)); | ||
_tcpOptions = (MqttClientTcpOptions)clientOptions.ChannelOptions; | ||
|
||
IsSecureConnection = clientOptions.ChannelOptions?.TlsOptions?.UseTls == true; | ||
} | ||
|
||
public MqttTcpChannel(Stream stream, string endpoint, X509Certificate2 clientCertificate) | ||
public MqttTcpChannel(Stream stream, string endpoint, X509Certificate2 clientCertificate) : this() | ||
{ | ||
_stream = stream ?? throw new ArgumentNullException(nameof(stream)); | ||
|
||
|
@@ -149,11 +155,15 @@ public async Task<int> ReadAsync(byte[] buffer, int offset, int count, Cancellat | |
return 0; | ||
} | ||
|
||
#if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER | ||
return await stream.ReadAsync(buffer.AsMemory(offset, count), cancellationToken).ConfigureAwait(false); | ||
#else | ||
// Workaround for: https://github.com/dotnet/corefx/issues/24430 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question: starting with .NET Core 3.0 this workaround isn't needed anymore, so the code could be conditionally compiled for a "legacy" target and for new targets. W/o the workaround perf in general should be better, as the cost of creating, and disposing the cancellationtoken-registration can be avoided. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it is fixed we should add a compiler switch (NETCOREAPP3_0_OR_GREATER). |
||
using (cancellationToken.Register(Dispose)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the above code I agree that the lambda is not required but here we already have a method without wrapping it. Do we really need that optimization here as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From my profiling it showed up in But when the conditional compilation is added for .NET Core 3.0 and newer, this won't be hit. So for the legacy code we could
I'm leaning to the latter, as the change isn't huge and so older targets can benefit from that change too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, now I see your concern. Yes we need it. Whether it's a delegate created from a method group or a lambda, the delegate won't be cached. Checked the IL for both. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK then we should keep it. |
||
using (cancellationToken.Register(_disposeAction)) | ||
{ | ||
return await stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); | ||
} | ||
#endif | ||
} | ||
catch (ObjectDisposedException) | ||
{ | ||
|
@@ -177,18 +187,22 @@ public async Task WriteAsync(byte[] buffer, int offset, int count, CancellationT | |
|
||
try | ||
{ | ||
// Workaround for: https://github.com/dotnet/corefx/issues/24430 | ||
using (cancellationToken.Register(Dispose)) | ||
{ | ||
var stream = _stream; | ||
var stream = _stream; | ||
|
||
if (stream == null) | ||
{ | ||
throw new MqttCommunicationException("The TCP connection is closed."); | ||
} | ||
if (stream == null) | ||
{ | ||
throw new MqttCommunicationException("The TCP connection is closed."); | ||
} | ||
|
||
#if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER | ||
await stream.WriteAsync(buffer.AsMemory(offset, count), cancellationToken).ConfigureAwait(false); | ||
#else | ||
// Workaround for: https://github.com/dotnet/corefx/issues/24430 | ||
using (cancellationToken.Register(_disposeAction)) | ||
{ | ||
await stream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); | ||
} | ||
#endif | ||
} | ||
catch (ObjectDisposedException) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the bug also fixed in this case so adding the pragma here works as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Socket.ConnectAsync(string, int, CancellationToken)
exists only starting from .NET 6.So for the moment we have to stay at the current code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.