-
Notifications
You must be signed in to change notification settings - Fork 763
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
Added Span support to Webencoders #334
Changes from 1 commit
6f416e3
1f7e3ff
a03d38d
26450cd
f32f46c
194b4ab
ca91b68
acd987c
72a362e
143a76c
09144d7
3681f18
d309378
007aa1a
6577241
4849dbc
bdc27dd
3e7f230
6c2ea6b
7d25346
39109e1
3b56276
46a5941
2e870a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -209,13 +209,13 @@ public static byte[] Base64UrlDecode(string input, int offset, char[] buffer, in | |
#if NETCOREAPP2_1 | ||
var data = new byte[dataLength]; | ||
var base64 = buffer.AsSpan(bufferOffset, base64Len); | ||
EncodingHelper.UrlDecode(input.AsSpan(offset, count), base64); | ||
UrlEncoder.UrlDecode(input.AsSpan(offset, count), base64); | ||
Convert.TryFromBase64Chars(base64, data, out int written); | ||
Debug.Assert(written == dataLength); | ||
|
||
return data; | ||
#else | ||
EncodingHelper.UrlDecode(input.AsSpan(offset, count), buffer.AsSpan(bufferOffset, base64Len)); | ||
UrlEncoder.UrlDecode(input.AsSpan(offset, count), buffer.AsSpan(bufferOffset, base64Len)); | ||
return Convert.FromBase64CharArray(buffer, bufferOffset, base64Len); | ||
#endif | ||
} | ||
|
@@ -363,7 +363,7 @@ public static OperationStatus Base64UrlEncode(ReadOnlySpan<byte> data, Span<byte | |
|
||
if (status == OperationStatus.Done || status == OperationStatus.NeedMoreData) | ||
{ | ||
bytesWritten = EncodingHelper.UrlEncode(base64Url, bytesWritten); | ||
bytesWritten = UrlEncoder.UrlEncode(base64Url, bytesWritten); | ||
} | ||
|
||
return status; | ||
|
@@ -494,7 +494,7 @@ private static int Base64UrlDecodeCoreSlow(ReadOnlySpan<char> base64Url, Span<by | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private static int Base64UrlDecodeCore(ReadOnlySpan<char> base64Url, Span<byte> base64Bytes, Span<byte> data) | ||
{ | ||
EncodingHelper.UrlDecode(base64Url, base64Bytes); | ||
UrlEncoder.UrlDecode(base64Url, base64Bytes); | ||
var status = Base64.DecodeFromUtf8(base64Bytes, data, out int consumed, out int written); | ||
|
||
if (status != OperationStatus.Done) | ||
|
@@ -531,7 +531,7 @@ private static OperationStatus Base64UrlDecodeCoreSlow(ReadOnlySpan<byte> base64 | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private static OperationStatus Base64UrlDecodeCore(ReadOnlySpan<byte> base64Url, Span<byte> base64, Span<byte> data, out int consumed, out int written, bool isFinalBlock) | ||
{ | ||
EncodingHelper.UrlDecode(base64Url, base64, isFinalBlock); | ||
UrlEncoder.UrlDecode(base64Url, base64, isFinalBlock); | ||
var status = Base64.DecodeFromUtf8(base64, data, out consumed, out written, isFinalBlock); | ||
|
||
if (status != OperationStatus.Done && status != OperationStatus.NeedMoreData) | ||
|
@@ -555,7 +555,7 @@ private static int Base64UrlEncodeCore(ReadOnlySpan<byte> data, Span<char> base6 | |
|
||
Span<char> base64 = stackalloc char[base64Len]; | ||
Convert.TryToBase64Chars(data, base64, out int written); | ||
return EncodingHelper.UrlEncode(base64, base64Url); | ||
return UrlEncoder.UrlEncode(base64, base64Url); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
|
@@ -566,7 +566,7 @@ private static int Base64UrlEncodeCoreSlow(ReadOnlySpan<byte> data, Span<char> b | |
{ | ||
var base64 = new Span<char>(arrayToReturnToPool = ArrayPool<char>.Shared.Rent(base64Len), 0, base64Len); | ||
Convert.TryToBase64Chars(data, base64, out int written); | ||
return EncodingHelper.UrlEncode(base64, base64Url); | ||
return UrlEncoder.UrlEncode(base64, base64Url); | ||
} | ||
finally | ||
{ | ||
|
@@ -598,7 +598,7 @@ private static int Base64UrlEncodeCore(ReadOnlySpan<byte> data, Span<char> base6 | |
ThrowHelper.ThrowOperationNotDone(status); | ||
} | ||
|
||
return EncodingHelper.UrlEncode(base64Bytes, base64Url); | ||
return UrlEncoder.UrlEncode(base64Bytes, base64Url); | ||
#if !NET461 | ||
} | ||
finally | ||
|
@@ -723,9 +723,8 @@ Exception GetInvalidArgumentsException() | |
} | ||
} | ||
|
||
// internal to make this testable | ||
// TODO: replace IntPtr and (int*) with nuint once available | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The other workaround we be defining an The TODO comment is to remind me for the change once available. |
||
internal static unsafe class EncodingHelper | ||
internal static unsafe class UrlEncoder | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rename this type |
||
{ | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void UrlDecode(ReadOnlySpan<byte> urlEncoded, Span<byte> base64, bool isFinalBlock = true) | ||
|
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.
Convert.TryToBase64Chars
is noticeable faster thanBase64.EncodeToUtf8
. Maybe because base64-encoding and byte -> char is done in one step.Interestingly on the decoding-methods the
Base64
-methods are faster.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.
/cc @ahsonkhan
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.
Last I checked (back in October), the span APIs were on par or faster: dotnet/corefx#24888
@atsushikan, recently did a port of the optimizations to the Convert methods: dotnet/coreclr#17033
There shouldn't be much difference on either now (in the general, non-allocating cases). Can you share details on what type of input you are measuring performance on and maybe a stripped down repro? Otherwise, I will take a deeper look in a couple of days. Thanks for bringing it up.
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.
Oh, I had the wrong suspects. Sorry. When running a stripped down sequential repo perf is on par, as noticed by @ahsonkhan
In the vectorized version the difference shows up.
will make the difference.
For
Base64.EncodeToUtf8
T
will bebyte
, so on AVX2Vector<T>.Count
is 32.For
Convert.TryToBase64Chars
T
will bechar
(or to be preciseushort
), henceVector<T>.Count
is 16.For a Guid
n
is 24. So the Convert-version will urlencode vectorized, whereas the Base64-version will run sequential only.