Repository navigation
Use the span based Convert APIs in the Base64 polyfill - #688
Merged
Merged
Conversation
This was referenced Oct 12, 2026
This was referenced Oct 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
Base64polyfill (net11 members) encoded and decoded throughsource.ToArray()and intermediate strings/arrays on every target.On
NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATERthe helpers now use the span based BCL APIs:EncodeToString->Convert.ToBase64String(ReadOnlySpan<byte>)EncodeToChars(source, destination)/TryEncodeToChars->Convert.TryToBase64Charsstraight into the destinationEncodeToChars(source)->Convert.TryToBase64Charsstraight into the result arrayDecodeFromChars/TryDecodeFromChars/DecodeFromUtf8(source)->Convert.TryFromBase64Charsinto a stack (up to 256 bytes) or pooled bufferOn every target
EncodeToUtf8(source)now callsBase64.EncodeToUtf8straight into a right-sized array instead of building a string and narrowing it.The contract is unchanged:
FormatException.Convert.TryFromBase64Charsreturnsfalsefor both invalid input and a destination that is too small, so the decode goes to a buffer ofsource.Length / 4 * 3bytes (the most that valid input can produce); afalsethen can only mean invalid input, and the array overload is called to throw the same exception as beforefalsewith0written (or throwsArgumentExceptionfromDecodeFromChars/EncodeToChars), invalid input still wins over a destination that is too small, and the destination is still only written to on successTargets without the span based
ConvertAPIs (net4x, netstandard2.0, netcoreapp2.0) keep the previous code for everything exceptEncodeToUtf8(source). TheOperationStatusoverloads are not touched here.Tests
Convertfor every length from 0 to 400 (all remainders, stack and pooled buffers), with a sentinel after the expected outputTryand throwing overloadsDecodeFromUtf8The real net11
Base64reports partial progress when the destination is too small and reports that ahead of later invalid input; the tests check those two points only where the polyfill is in use (runtime check), everything else runs against both.Measurements
Stopwatch /
GC.GetAllocatedBytesForCurrentThread, Release, minimum of 4 alternating runs of before and after (each the best of 9 rounds after warm-up).net10.0
EncodeToString(32B)EncodeToString(1KB)EncodeToChars(32B, dest)EncodeToChars(1KB, dest)EncodeToChars(1KB)TryEncodeToChars(1KB, dest)EncodeToUtf8(32B)EncodeToUtf8(1KB)DecodeFromChars(32B)DecodeFromChars(1KB)DecodeFromChars(1KB, dest)TryDecodeFromChars(1KB, dest)DecodeFromUtf8(1KB)net48 (only
EncodeToUtf8(source)changes)EncodeToUtf8(32B)EncodeToUtf8(1KB)