Skip to content

Conversation

@henryiii
Copy link
Contributor

@henryiii henryiii commented Jan 19, 2026

On Python 3.12 and 3.13, str.translate is really slow. This is less elegant, but much faster on those two Python versions, and a bit faster on the other Python versions.

Change Before [d5398b8] After [712338f] <henryiii/perf/doublerepl> Ratio Benchmark (Parameter)
- 5.91±0.01μs 3.11±0μs 0.53 utils.TimeUtils.time_canonicalize_name [PU-H2WF61JRQ6NY/virtualenv-py3.8]
- 5.88±0.02μs 3.16±0.03μs 0.54 utils.TimeUtils.time_canonicalize_name [PU-H2WF61JRQ6NY/virtualenv-py3.9]
- 5.98±0.02μs 3.09±0.01μs 0.52 utils.TimeUtils.time_canonicalize_name [PU-H2WF61JRQ6NY/virtualenv-py3.10]
- 5.06±0.01μs 2.36±0.02μs 0.47 utils.TimeUtils.time_canonicalize_name [PU-H2WF61JRQ6NY/virtualenv-py3.11]
- 9.51±0.04μs 2.42±0.04μs 0.25 utils.TimeUtils.time_canonicalize_name [PU-H2WF61JRQ6NY/virtualenv-py3.12]
- 9.64±0.01μs 2.37±0.01μs 0.25 utils.TimeUtils.time_canonicalize_name [PU-H2WF61JRQ6NY/virtualenv-py3.13]
- 3.96±0.04μs 3.09±0.05μs 0.78 utils.TimeUtils.time_canonicalize_name [PU-H2WF61JRQ6NY/virtualenv-py3.14]

This fixes a performance regression for Python 3.12 and 3.13 (#1030 is faster for all other Python versions), and is faster on all current Python versions.

Screenshot 2026-01-19 at 12 16 34 PM

(I suspect that .translate could be made faster in the future, as logically it could be faster, I think a lot more work went into optimizing .replace, there's a specialized fast path for one char replace) Edit: actually, not so sure. Translate is processing every char, while replace can do a vectorized copy, then scan looking for a single character replacement (there's a fast path for one char replacements). For a small number of chars, this is going to be faster than a hash table lookup and one byte builder. Optimizing translate to complete might be tricky.

CC @hugovk, not as important for CPython, where this is only marginally faster, but very nice for libraries that run on 3.12 and 3.13. str.translate is really slow in those versions.

Credit to @sirosen for coming up with this alternative, I was thinking about falling back to the old method on CPython 3.12 and 3.13. :)

Signed-off-by: Henry Schreiner <[email protected]>
@henryiii henryiii force-pushed the henryiii/perf/doublerepl branch from 712338f to a459db8 Compare January 19, 2026 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants