-
Notifications
You must be signed in to change notification settings - Fork 873
Reduce object allocations in UserCrypto.Decrypt by 98% for .NET8+ #4222
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
Reduce object allocations in UserCrypto.Decrypt by 98% for .NET8+ #4222
Conversation
| #if NET8_0_OR_GREATER | ||
| dataIn = Convert.FromHexString(encrypted); | ||
| #else | ||
| // Legacy behavior preserved for older TFMs |
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.
Nit: Fix the indentation for the legacy behavior here.
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.
done
| "updateMinimum": true, | ||
| "type": "patch", | ||
| "changeLogMessages": [ | ||
| "optimize user crypto decrypt" |
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.
What do you think of using the PR title (Reduce object allocations in UserCrypto.Decrypt by 98% for .NET8+) here instead? I think customers would find that easier to parse :)
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.
i like that better, updated :)
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.
Pull request overview
This PR optimizes the UserCrypto.Decrypt method to reduce memory allocations by 98% for .NET 8+ users on Windows. The method is a hot path for Windows machines when decrypting settings stored in the persistence manager. The original implementation used String.Substring in a loop to parse hex strings, creating many small string allocations. The optimization uses Convert.FromHexString for .NET 8+ to perform the conversion in a single operation, while preserving the legacy behavior for older target frameworks.
Key Changes:
- Replaced loop-based hex string parsing with
Convert.FromHexStringfor NET8_0_OR_GREATER - Used conditional compilation to maintain backward compatibility with older frameworks
- Added dev config file with patch version bump and changelog entry
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| sdk/src/Core/Amazon.Runtime/Internal/Settings/UserCrypto.cs | Optimized hex string to byte array conversion using Convert.FromHexString for .NET 8+, with conditional compilation to preserve legacy behavior for older TFMs |
| generator/.DevConfigs/a3466402-916b-4e40-8822-79b28ab5de33.json | Added dev config file with patch version bump and changelog message for the core optimization |
| // Legacy behavior preserved for older TFMs | ||
| List<byte> dataInList = new List<byte>(); | ||
| for (int i = 0; i < encrypted.Length; i = i + 2) | ||
| { | ||
| byte data = Convert.ToByte(encrypted.Substring(i, 2), 16); | ||
| dataIn.Add(data); | ||
| dataInList.Add(data); | ||
| } | ||
| dataIn = dataInList.ToArray(); |
Copilot
AI
Dec 12, 2025
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.
The indentation in the #else block is inconsistent. Lines 41, 42, and 48 use 4 spaces instead of the standard indentation. They should be indented with 12 spaces to align with the surrounding code at the same level as line 39.
Co-authored-by: Copilot <[email protected]>
|
Out of curiosity do you have any part of your profile stored in the legacy .NET store that uses UserCrypto? I'm wondering why the code even went down this path into .NET legacy store. |
Not that i'm aware of? I just used the default profile in |
|
merged for now, but i think it's worth looking at why this is getting called |

Description
This optimization is primarily for windows users.
UserCrypto.Decryptis a hot path for windows machines, and it was doing unnecessary string allocations. Here is the code snippet that was doing the allocations.For each iteration we were: allocating a new 2-char string via Substring(i, 2), call Convert.ToByte(string, 16) which parses that string. So if the hex string is length ~9,760, the loop runs ~4,880 times and creates 4,880 tiny strings. (which was my case). This method is called when decrypting any setting stored in the persistence manager.

In newer versions of .NET (.NET 5+) we can just use
Convert.FromHexStringand do it all in one byte array and much faster.In my profiling of looping a PutObject call 10 times, I saw the allocations for this specific method go down by 98% and in total by 23%.
Motivation and Context
Performance improvement for windows users
Testing
Dry run passed
Screenshots (if appropriate)
Pre Optimization

Post Optimization
Types of changes
Checklist
License