perf: speed up percent_decode using bulk run-copying - #1202
Merged
anonrig merged 3 commits intoJul 31, 2026
Conversation
Rewrite `percent_decode` to write into a single pre-sized buffer, copying plain
runs in bulk via `memchr('%')` and decoding `%XX` escapes through the branchless
`unhex_table`, then shrinking to the final length. This replaces the byte-at-a-time
append loop and mirrors the approach already used by `form_urlencoded_decode`.
Decoding never grows the input, so the output buffer is sized once up front.
Add `benchmarks/percent_decode.cpp` covering sparse, densely-encoded, long-plain-run, and utf-8 inputs.
~1.48x faster on the new benchmark (54.3 -> 36.4 ns/url; 1.03 -> 1.54 GB/s).
Member
|
Nice work! |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1202 +/- ##
==========================================
+ Coverage 61.06% 61.14% +0.08%
==========================================
Files 38 38
Lines 6939 6947 +8
Branches 3231 3231
==========================================
+ Hits 4237 4248 +11
+ Misses 749 748 -1
+ Partials 1953 1951 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
anonrig
reviewed
Jul 31, 2026
Member
It has regressions... That's why we couldn't land it. |
anonrig
enabled auto-merge (squash)
July 31, 2026 18:18
anonrig
approved these changes
Jul 31, 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.
Speed up
ada::unicode::percent_decode, the routine that decodes%XXescapes when parsing hosts (viato_ascii) and search-param values.The decoded output is never longer than the input, size the result buffer once and copy plain runs in bulk; the same approach
form_urlencoded_decodealready uses.What changed
input.size()and shrink to the final length at the end, instead ofreserve+ per-byte+=.%) spans are located withstd::memchr('%')and copied with a singlestd::memcpy, rather than appending one character at a time.%XXruns are decoded through the existingunhex_table(two loads + an OR to validate), which is above the function so bothpercent_decodeandform_urlencoded_decodeshare it.benchmarks/percent_decode.cpp, mirroringpercent_encode.cpp.Benchmark results
Measured with a Apple M5 (
benchmarks/percent_decode,--benchmark_min_time=1s):Decodetime/urlDecodethroughputTesting
clang-format,clang-tidyintroduces no new findings%,%2,%%41,%g0, trailing%, doubly-encoded, some utf-8 strings)Edit: side-note, just noticed #1124 which might be a longer term solution; feel free to close this if thats the preferred path.