Repository navigation
Update Sanitizer - #145
Merged
Merged
Update Sanitizer#145
Conversation
ecbadeaux
force-pushed
the
fast-sanitizer
branch
3 times, most recently
from
October 19, 2026 05:35
d1d3931 to
c553252
Compare
ecbadeaux
force-pushed
the
fast-sanitizer
branch
from
October 19, 2026 05:36
c553252 to
73111cf
Compare
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.
Replace regex tag sanitizer with a table-driven one
Summary
MeterIdbuilt its spectatord id by runningstd::regex_replaceon the name and on every tag key and value, then joining them with anostringstream. This was the dominant cost ofr.CreateCounter(name, tags). This PR replaces it with a compile-time lookup table and a single pre-sized string.AppendSanitizedwrites each byte askValidChars[byte] ? byte : '_'. The 256-entry table is built by aconstexprfunction, so nothing runs at startup. The old globalstd::regexis gone.ToSpectatorIdcomputes the exact output size, reserves once, and appends with noostringstream.meter_id.hstill includes<regex>so code that relied on it keeps compiling.Why this is faster than the per-character version
Google Benchmark on an id with a 35-character name and 7 tags:
ostringstream)+=with range checksBoth new versions reserve the output up front, so neither reallocates. The difference is what happens per character.
+=: reserving does not change the size, so every append still increases the string's size by one. Each iteration writes the new size back, stores the byte, rewrites the trailing NUL, and re-checks short-string vs heap mode. The generated code makes an out-of-linepush_backcall per character for the name.