Skip to content

perf: Antiforgery token validation & generation #61989

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

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

DeagleGross
Copy link
Member

@DeagleGross DeagleGross commented May 19, 2025

IN PROGRESS

main stats for benchmark

OS Method Mean Error StdDev Gen0 Gen1 Gen2 Allocated
win Generate 7,175.2 ns 4.19 ns 3.50 ns 0.1297 - - 4096 B
win ValidateWithUser 768.0 ns 2.52 ns 2.35 ns 0.0334 0.0010 0.0010 -
win Validate 144.4 ns 0.21 ns 0.18 ns 0.0045 0.0005 0.0005 120 B

{PR title}

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Summary of the changes (Less than 80 chars)

Description

{Detail}

Fixes #{bug number} (in this specific format)

@github-actions github-actions bot added the area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions label May 19, 2025
{
return false;
}

var areEqual = true;
for (var i = 0; i < a.Length; i++)
for (int i = 0; i < a.Length; i++)
Copy link
Member

Choose a reason for hiding this comment

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

Here in ASP.NET Core the convention is to use var, so please undo that change.

Suggested change
for (int i = 0; i < a.Length; i++)
for (var i = 0; i < a.Length; i++)

Same on other places (I'll just leave a short comment over there, so you can find these easier).

Copy link
Member Author

Choose a reason for hiding this comment

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

this is only a draft PR @gfoidl, I wont yet address PR comments. I need to confirm I am getting perf improvement here. I will come back to the comments later

var tokenLength = serializedToken.Length;
var charsRequired = WebEncoders.GetArraySizeRequiredToDecode(tokenLength);

var chars = charsRequired < 128 ? stackalloc byte[128] : (rented = ArrayPool<byte>.Shared.Rent(charsRequired));
Copy link
Member

Choose a reason for hiding this comment

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

Move the 128 to a named constant like StackAllocTheshold or similar.

var chars = charsRequired < 128 ? stackalloc byte[128] : (rented = ArrayPool<byte>.Shared.Rent(charsRequired));
chars = chars[..charsRequired];

var decodedResult = WebEncoders.TryBase64UrlDecode(
Copy link
Member

Choose a reason for hiding this comment

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

Starting with .NET 9 the built-in Base64Url methods could be used. They're faster than WebEncoders-version due to vectorization.

Nice that use WebEncoders here as shim for the built-in methods 👍🏻
(When reading the PR first, I thought that's missed)

@@ -119,6 +139,41 @@ public DefaultClaimUidExtractor(ObjectPool<AntiforgerySerializationContext> pool
return identifierParameters;
}

private static void ComputeSha256(IEnumerable<string> parameters, Span<byte> output, out int bytesWritten)
{
int estimatedSize = 0;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int estimatedSize = 0;
var estimatedSize = 0;

int estimatedSize = 0;
foreach (var param in parameters)
{
int byteCount = Encoding.UTF8.GetByteCount(param);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int byteCount = Encoding.UTF8.GetByteCount(param);
var byteCount = Encoding.UTF8.GetByteCount(param);

int offset = 0;
foreach (var param in parameters)
{
int byteCount = Encoding.UTF8.GetByteCount(param);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int byteCount = Encoding.UTF8.GetByteCount(param);
var byteCount = Encoding.UTF8.GetByteCount(param);

Comment on lines +33 to +34
int result = 0;
int shift = 0;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int result = 0;
int shift = 0;
var result = 0;
var shift = 0;

throw new InvalidOperationException("Invalid 7-bit encoded int.");
}

byte b = span[bytesRead++];
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
byte b = span[bytesRead++];
var b = span[bytesRead++];


internal static class ReadOnlySpanExtensions
{
public static bool BinaryReadBoolean(this ReadOnlySpan<byte> span, ref int offset)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
public static bool BinaryReadBoolean(this ReadOnlySpan<byte> span, ref int offset)
public static bool BinaryReadBooleanAndAdvance(this ReadOnlySpan<byte> span, ref int offset)

? Otherwise the side effect of offset++ maybe astonishing.
Or add an xml-doc comment.

Comment on lines +20 to +21
int length = span.Read7BitEncodedInt(out int prefixLength);
int stringEnd = prefixLength + length;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int length = span.Read7BitEncodedInt(out int prefixLength);
int stringEnd = prefixLength + length;
var length = span.Read7BitEncodedInt(out int prefixLength);
var stringEnd = prefixLength + length;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants