Skip to content

Adds JsonWebToken Constructor that accepts Memory<char>#2458

Merged
sruke merged 44 commits into
devfrom
sruthi/JsonWebTokenSpan
Feb 25, 2024
Merged

Adds JsonWebToken Constructor that accepts Memory<char>#2458
sruke merged 44 commits into
devfrom
sruthi/JsonWebTokenSpan

Conversation

@sruke

@sruke sruke commented Jan 24, 2024

Copy link
Copy Markdown
Contributor

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.

Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs Outdated
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs Outdated
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs Outdated
Comment thread buildConfiguration.xml Outdated
// 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
Copy Markdown
Contributor

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
Copy Markdown
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.

Comment thread benchmark/Microsoft.IdentityModel.Benchmarks/EncodedJWTs.cs Outdated
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs Outdated
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/Base64UrlEncoder.cs Outdated
@sruke sruke force-pushed the sruthi/JsonWebTokenSpan branch from 3e91f27 to 1a96d3e Compare February 1, 2024 17:58
@sruke sruke force-pushed the sruthi/JsonWebTokenSpan branch from 59cfab2 to abdd893 Compare February 2, 2024 21:26
@sruke sruke changed the title Adds JsonWebToken Constructor that accepts a Span Adds JsonWebToken Constructor that accepts Memory<char> Feb 2, 2024
Comment thread benchmark/Microsoft.IdentityModel.Benchmarks/ReadTokenTests.cs Outdated
Comment thread benchmark/Microsoft.IdentityModel.Benchmarks/ReadTokenTests.cs
@Saibamen

Saibamen commented Feb 12, 2024

Copy link
Copy Markdown

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

@Saibamen

Saibamen commented Feb 12, 2024

Copy link
Copy Markdown

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/

Comment thread benchmark/Microsoft.IdentityModel.Benchmarks/ReadTokenTests.cs Outdated
@sruke

sruke commented Feb 13, 2024

Copy link
Copy Markdown
Contributor Author

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

sruke commented Feb 20, 2024

Copy link
Copy Markdown
Contributor Author

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

Comment thread build/releaseBuild.yml
Comment thread build/releaseBuild.yml
Comment thread benchmark/Microsoft.IdentityModel.Benchmarks/ReadJWETokenTests.cs Outdated
Comment thread benchmark/Microsoft.IdentityModel.Benchmarks/ReadJWSTokenTests.cs
Comment thread benchmark/Microsoft.IdentityModel.Benchmarks/ReadJWSTokenTests.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/Base64UrlEncoding.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/Base64UrlEncoding.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/Base64UrlEncoding.cs Outdated
Comment thread test/Microsoft.IdentityModel.Tokens.Tests/Base64UrlEncodingTests.cs Outdated
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs Outdated
Comment thread test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenTests.cs Outdated
sruke and others added 8 commits February 23, 2024 16:10
…ests.cs

Co-authored-by: Peter <34331512+pmaytak@users.noreply.github.com>
Co-authored-by: Peter <34331512+pmaytak@users.noreply.github.com>
…ts.cs

Co-authored-by: Peter <34331512+pmaytak@users.noreply.github.com>
Comment thread benchmark/Microsoft.IdentityModel.Benchmarks/ReadJWETokenTests.cs

@jennyf19 jennyf19 left a comment

Copy link
Copy Markdown
Contributor

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
@Saibamen

Copy link
Copy Markdown

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

Development

Successfully merging this pull request may close these issues.

[Feature Request] Add a JsonWebToken Constructor that accepts ReadOnlyMemory representation of the encodedToken

7 participants