Reduce some allocations in SslStream handshake.#103814
Conversation
| byte[]? hash = null; | ||
|
|
||
| if (sslAuthenticationOptions.CertificateContext?.TargetCertificate is X509Certificate2 cert) | ||
| { | ||
| // This is equivalent to cert.GetCertHash(HashAlgorithmName.Sha256), but this | ||
| // way the code does not allocate a new byte[] with raw cert contents.every time | ||
| hash = SHA256.HashData(cert.RawDataMemory.Span); | ||
| } | ||
|
|
||
| var key = new SslContextCacheKey(protocols, hash); |
There was a problem hiding this comment.
@bartonjs is the X509Certificate.GetCertHash(...) behavior by design? looks like something that could potentially help in multiple places if we can change the implementation to use the internaly cached RawData.
There was a problem hiding this comment.
(Not Jeremy, but...) I don't think so. We can probably make some improvements here.
There was a problem hiding this comment.
Since it's using certPal.RawData instead of this.RawData, I think it's trying to avoid the allocation; but clearly some PALs are caching that and others are not, because we started off with a weak PAL contract and haven't ever cleaned it up.
In this case, it looks like just switching from certPal.RawData to this.RawDataMemory.Span will mean we know exactly what caching is involved.
There was a problem hiding this comment.
With #103828 merged I am not sure this is needed anymore.
| private static SslProtocols FilterOutIncompatibleSslProtocols(SslProtocols protocols) | ||
| { | ||
| if (protocols.HasFlag(SslProtocols.Tls12) || protocols.HasFlag(SslProtocols.Tls13)) | ||
| if ((protocols & (SslProtocols.Tls12 | SslProtocols.Tls13)) != SslProtocols.None) |
There was a problem hiding this comment.
The change is fine, but did you see this allocating?
There was a problem hiding this comment.
I collected a trace via dotnet trace and saw an entry for this. The signature is apparently
public bool HasFlag (Enum flag);so I assume it is boxing the argument. The trace was in Debug configuration, I am not sure if it happens in Release as well.
There was a problem hiding this comment.
I am not sure if it happens in Release as well.
The JIT special-cases HasFlag. It shouldn't be allocating in optimized code.
There was a problem hiding this comment.
The trace was in Debug configuration
You generally don't want to do any perf analysis based on debug. Optimizations are disabled, both at the JIT level and also the C# level (e.g. async methods get emitted as classes rather than structs), so it provides a skewed view of the world.
There was a problem hiding this comment.
I got unsure and rechecked the trace, it indeed comes from a different place. But I don't see it in the most recent traces for some reason.
dfeca77 to
50a9450
Compare
This removes some unnecessary allocations on TLS handshakes, mostly on Linux.