GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||
GeezerVison is showing github.com — gh-161145: Test more bytes simultaneously in find_first_nonascii by cmaloney · Pull Request #161147 · python/cpython Conversation
|
| Benchmark | main | this |
|---|---|---|
| (b'a' * 4096).decode() | 165 ns | 108 ns: 1.53x faster |
| (b'a' * 200).decode() | 28.9 ns | 26.5 ns: 1.09x faster |
| b'a' * 200 + 'é' + ..., .decode() | 60.9 ns | 56.0 ns: 1.09x faster |
| b'a' * 136 + 'é' + ..., .decode() | 53.8 ns | 51.3 ns: 1.05x faster |
| 8-100 byte decodes, 'é' within 100 | within 1.2 ns |
import pyperf runner = pyperf.Runner() tail = 'é'.encode() + b'a' * 50 for n in (8, 100, 200, 4096): runner.timeit(f"(b'a' * {n}).decode()", "s.decode()", globals={"s": b'a' * n}) for n in (16, 100, 136, 200): runner.timeit(f"(b'a' * {n} + 'é'.encode() + b'a' * 50).decode()", "s.decode()", globals={"s": b'a' * n + tail})
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Long ASCII runs now OR eight aligned words and test the high bits once, one branch per 64 bytes (32 on 32-bit) instead of one per word. When a block contains a non-ASCII byte, the existing one-word loop finds it. It is plain C: GCC and Clang compile it to SSE2/NEON loads, other compilers to ORed word loads with the same single branch. Multiple compiler and architecture codegen sample: https://godbolt.org/z/8bM83vx3a pyperf, PGO+LTO, 2 interleaved rounds: | Benchmark | main | this | |---|---:|---:| | (b'a' * 4096).decode() | 165 ns | 108 ns: 1.53x faster | | (b'a' * 200).decode() | 28.9 ns | 26.5 ns: 1.09x faster | | b'a' * 200 + 'é' + ..., .decode() | 60.9 ns | 56.0 ns: 1.09x faster | | b'a' * 136 + 'é' + ..., .decode() | 53.8 ns | 51.3 ns: 1.05x faster | | 8-100 byte decodes, 'é' within 100 | | within 1.2 ns | ```python import pyperf runner = pyperf.Runner() tail = 'é'.encode() + b'a' * 50 for n in (8, 100, 200, 4096): runner.timeit(f"(b'a' * {n}).decode()", "s.decode()", globals={"s": b'a' * n}) for n in (16, 100, 136, 200): runner.timeit(f"(b'a' * {n} + 'é'.encode() + b'a' * 50).decode()", "s.decode()", globals={"s": b'a' * n + tail}) ``` Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
See #122902 which is similar. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.