Performance and Safety Improvements#3
Conversation
…ve exception handling - Replace LINQ Take/Skip/ToArray with Span<T> and ReadOnlySpan<T> slicing for zero-allocation subarray access. - Minimize temporary array allocations and unnecessary data copying, especially in cryptographic and handshake routines. - Expose sensitive data and internal buffers as read-only properties or ReadOnlySpan<T> to prevent accidental modification and enforce immutability. - Centralize exception throwing into non-inlineable helper methods (e.g., Throw.NotSupportedException, Throw.TlsFatalAlert) to allow JIT inlining of hot-path methods. - Add defensive checks to fail fast on invalid state, improving safety and predictability. - All changes are compatible with .NET Standard 2.0 and .NET 8. These changes reduce GC pressure, improve throughput, and make the codebase safer and more maintainable for high-performance and security-sensitive scenarios.
- Simplify test assertion output by using BitConverter.ToString for clearer, more readable hex comparisons in test failures. - Add [SkipLocalsInit] to key methods to improve performance by skipping local variable zero-initialization. - Refactor buffer slicing in SRTP encryption functions for clarity and to prevent potential length/offset bugs.
|
I'd like to create tests for the untested parts. Any suggestions? I also thing some properties, like keys, should be locked for access from external code and |
|
Why are |
The idea was in case there is a newer crypto algorithm added in the future, people could simply add it by extending the class. |
Caching KeyParameter is a good idea, that would reduce the number of allocations. I don't see much benefit in "locking access" from external code, in the end you can always use reflection or dump it from the memory if you try really hard. See here https://github.com/jimm98y/AnsysDiscoveryD3DEnabler for instance. My most recent experience with "locked access" resulted in a few bad workarounds to accomplish my goal - see https://github.com/jimm98y/SharpOnvif/blob/32699624b9cff9801cc1b3eefad1741771859bdc/src/SharpOnvifClient/Security/HttpDigestProxy.cs#L115 and https://github.com/jimm98y/SharpOnvif/blob/32699624b9cff9801cc1b3eefad1741771859bdc/src/SharpOnvifClient/Security/HttpDigestHeaderInspector.cs#L141. I'd prefer to avoid putting developers in the same situations with my APIs... |
Performance and Safety Optimizations
Overview
This PR introduces a comprehensive set of memory, allocation, and safety optimizations across the codebase. The changes are designed to reduce unnecessary allocations and data copying, improve performance through the use of spans, and enforce immutability and safer exception handling patterns.
Memory and Allocation Improvements
Why These Changes?
Span<T>andReadOnlySpan<T>enable lightweight, stack-only views over arrays and buffers, eliminating the need for new array allocations.Spans provide direct access to subranges of data, avoiding the overhead and latency of copying.
Fewer allocations mean less work for the garbage collector, resulting in lower latency and higher throughput.
Span operations are simple and predictable, allowing the JIT to optimize them aggressively.
Using spans clarifies that you are working with a view, not a copy, preventing accidental modifications.
What Was Changed?
Refactored code to avoid creating temporary arrays, especially in cryptographic and handshake routines.
Take,Skip, andToArraywith Span Slicing:All usages of these LINQ methods for subarray extraction have been replaced with
Span<T>orReadOnlySpan<T>slicing, eliminating unnecessary heap allocations and data copying.Where compatible, replaced array-based APIs and LINQ subsetting with
Span<T>/ReadOnlySpan<T>slicing, enabling stack-based, allocation-free operations.Immutability and API Safety
Parameters and properties are now marked as
readonlyor exposed asReadOnlySpan<T>/IReadOnlyList<T>where possible, preventing accidental modification of sensitive data.Public properties that expose internal state are now read-only, ensuring consumers cannot mutate internal buffers or collections.
Exception Handling and Inlining
Exception throwing is centralized into dedicated helper methods (e.g.,
Throw.NotSupportedException(),Throw.TlsFatalAlert()), which are explicitly marked as non-inlineable.Defensive checks now throw immediately using these helpers, reducing the risk of undefined behavior.
Compatibility
Summary
This PR makes the library more robust, performant, and secure. By reducing allocations, enforcing immutability, using span slicing instead of LINQ, and optimizing exception handling, the codebase is better suited for high-performance and security-sensitive applications.
Please review the changes with a focus on: