Skip to content
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

Adds JsonWebToken Constructor that accepts Memory<char> #2458

Merged
merged 44 commits into from Feb 25, 2024

Conversation

sruke
Copy link
Contributor

@sruke sruke commented Jan 24, 2024

Introduces a JsonWebToken Constructor that accepts ReadOnlyMemory representation of the encodedToken

Description

This PR

  • Introduces a JsonWebToken constructor that accepts ReadOnlyMemory representation of the encodedToken
  • Updates existing JsonWebToken constructors to use string.AsMemory() to maintain a single code path
  • ReadTokens(..) Uses Memory.Span to extract the token segments such as the header, payload, encryptedKeyBytes etc.
  • Refactors CreateClaimSet by moving ArrayPool usage into the JsonWebToken that reduces memory allocation by 4.6% during JWS creation.

Performance Assessment on .NET 8:
When using the preview version and opting for the constructor that accepts a string for the encoded token, the generation of a JWS yields a 3.95% decrease in memory usage, a 4.52% reduction in Gen0, and a 4.61% decrease in execution time compared to the latest release. The performance of the constructor that accepts ReadOnlyMemory is comparable to the constructor accepting a string for the encoded token, both for JWS and JWE.

Preview branch:
image

Dev (main) branch:
image

Why?
The new constructor allows a customer to leverage spans for slicing the encoded token directly from the Authorization Header eliminating additional String.Split operations on their end and can further improve performance.

buildConfiguration.xml Outdated Show resolved Hide resolved
// empty payload for JWE's {encrypted tokens}.
Payload = new JsonClaimSet();

if (dotIndex == encodedJsonSpanCopy.Length) // TODO: Should this be encodedJsonSpanCopy.Length - 1? Using encodedJsonSpanCopy.Length doesn't add up
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Length

what's the issue with .Length? 'dotIndex' is the first dot character, so I'd think dotIndex == encodedJsonSpanCopy.Length would work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking is that the value of EncodedJsonSpanCopy.Length will fall outside the range of the string and EncodedJsonSpanCopy.Length - 1 would be more appropriate.

@sruke sruke changed the title Adds JsonWebToken Constructor that accepts a Span Adds JsonWebToken Constructor that accepts Memory<char> Feb 2, 2024
@Saibamen
Copy link

Saibamen commented Feb 12, 2024

In BenchmarkDotNet.Artifacts\results folder, you have *.md file to copy and paste markdown table, no need to make screenshots

@Saibamen
Copy link

Saibamen commented Feb 12, 2024

ReadJWE_FromString has less allocations in current master branch

You can use profiling to search for more optimization: https://devblogs.microsoft.com/visualstudio/a-look-back-visual-studios-profiling-tool-advancements-in-2023/

@sruke
Copy link
Contributor Author

sruke commented Feb 13, 2024

ReadJWE_FromString has less allocations in current master branch

You can use profiling to search for more optimization: https://devblogs.microsoft.com/visualstudio/a-look-back-visual-studios-profiling-tool-advancements-in-2023/

Yes I have noticed and working towards finding a way to reduce allocations using the profiler.

@sruke
Copy link
Contributor Author

sruke commented Feb 20, 2024

ReadJWE_FromString has less allocations in current master branch
You can use profiling to search for more optimization: https://devblogs.microsoft.com/visualstudio/a-look-back-visual-studios-profiling-tool-advancements-in-2023/

Yes I have noticed and working towards finding a way to reduce allocations using the profiler.

ReadJWE_FromString has less allocations in current master branch

You can use profiling to search for more optimization: https://devblogs.microsoft.com/visualstudio/a-look-back-visual-studios-profiling-tool-advancements-in-2023/

ReadJWE_FromString has less allocations in current master branch
You can use profiling to search for more optimization: https://devblogs.microsoft.com/visualstudio/a-look-back-visual-studios-profiling-tool-advancements-in-2023/

Yes I have noticed and working towards finding a way to reduce allocations using the profiler.

@keegan-caruso found that ReadJWETokenTests is not an appropriate benchmark for assessing JWE creation performance. Claims are not populated during JsonWebToken creation since the token is encrypted; they are only populated during validation when the token is decrypted. ValidateJWEAsyncTests is a more suitable benchmarks that creates and validates a JWE. On running this benchmark, there is no performance concern. There is a .5% reduction in memory allocation.

sruthi/JsonWebTokenSpan

BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.22631.3007), VM=Hyper-V
AMD EPYC 7763, 1 CPU, 16 logical and 8 physical cores
.NET SDK=8.0.200-preview.23624.5
  [Host]    : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
  MediumRun : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2

Job=MediumRun  MaxAbsoluteError=10.0000 ms  IterationCount=15  
LaunchCount=4  WarmupCount=10  
Method Mean Error StdDev P90 P95 P100 Gen0 Gen1 Allocated
JsonWebTokenHandler_ValidateJWEAsync 40.20 μs 0.113 μs 0.252 μs 40.56 μs 40.63 μs 40.90 μs 0.9766 0.1221 16.2 KB

dev

BenchmarkDotNet=v0.13.5, OS=Windows 11 (10.0.22631.3007), VM=Hyper-V
AMD EPYC 7763, 1 CPU, 16 logical and 8 physical cores
.NET SDK=8.0.200-preview.23624.5
  [Host]    : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
  MediumRun : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2

Job=MediumRun  MaxAbsoluteError=10.0000 ms  IterationCount=15  
LaunchCount=4  WarmupCount=10  
Method Mean Error StdDev P90 P95 P100 Gen0 Gen1 Allocated
JsonWebTokenHandler_ValidateJWEAsync 40.33 μs 0.133 μs 0.286 μs 40.61 μs 40.72 μs 41.39 μs 0.9766 0.1221 16.29 KB

Copy link
Collaborator

@jennyf19 jennyf19 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

Sruthi Keerthi Rangavajhula (from Dev Box) added 2 commits February 25, 2024 11:01
@sruke sruke merged commit d5dc77e into dev Feb 25, 2024
3 of 4 checks passed
@Saibamen
Copy link

Can you paste final benchmark results here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants