-
-
Notifications
You must be signed in to change notification settings - Fork 132
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
Memory optimization #39 #40
base: master
Are you sure you want to change the base?
Conversation
Instead of allocating new byte arrays each time you perform a cryptographic operation (such as signing, encryption, or converting data to/from Base64), you can use a buffer pool. A buffer pool maintains a set of preallocated buffers that can be reused, reducing the need for frequent allocations. In .NET, the ArrayPool<T> class is ideal for this purpose.
The code has been updated to use XmlReader and XmlWriter for efficient XML parsing and writing. This change improves the performance of loading and saving licenses by ignoring unnecessary whitespace during reading, and enabling indentation during writing.
Introduced a static XmlReaderSettings object with pre-configured settings to optimize XML parsing in the License class. This change reduces unnecessary processing by ignoring whitespace, comments, and processing instructions during XML reading. The new settings are now used when creating an XmlReader instance for loading licenses from a stream.
While the improvements are small, it is still an improvement (#39): Here’s a breakdown of what the benchmark tells us:
ConclusionThe improvements are minimal, but the fact that you’ve reduced both time and memory usage means the changes are effective, albeit small. It suggests that unless you need to further optimize for more significant performance gains, the new method is slightly more efficient, especially in scenarios where these small improvements can compound over many operations. |
using (var rng = RandomNumberGenerator.Create()) | ||
{ | ||
rng.GetBytes(salt, 0, 16); | ||
} |
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.
You could tighten this line up a bit and get rid of the using with a change to using the static Fill()
method:
RandomNumberGenerator.Fill(salt.AsSpan(0,16));
Hi @kfrancis, |
Unfortunately I don't think I kept the benchmark.net code, but I imagine I was trying to do net48, net80 as some of our code lives in both. |
Hi @kfrancis, The issue is with the Its a subtle problem, and I missed it myself on the first glance, but in thinking about it further I realized that this creates a fundamental behavior change. I believe the idea is for the salt to be explicitly 16 bytes long, so that change probably needs to be removed from this PR. I can't speak for the XML changes you made and I have no connection with the project (other than I had an original fork several years ago to support .NET 5.0). The ideal solution for the key encryption is when (and if) BouncyCastle adds more support for spans, then in the .NET 6.0+ targets rather than creating a new array, we could use stackalloc for the salt buffer, but for now that is not supported. |
secureRandom.SetSeed(secureRandom.GenerateSeed(16)); //See Bug #135 | ||
secureRandom.NextBytes(salt); | ||
// Rent a buffer for the salt (16 bytes for the salt) | ||
var salt = ArrayPool<byte>.Shared.Rent(16); |
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.
Potential issue here as the salt array is no longer guaranteed to be 16 bytes long.
No description provided.