gpshead · GitHub

Add Tools/binasciibench/binasciibench.py benchmark for measuring base64
encoding/decoding throughput.
Optimize base64 encoding/decoding by eliminating loop-carried dependencies.
Key changes:
- Add base64_encode_trio() and base64_decode_quad() helper functions
  that process complete groups independently
- Add base64_encode_fast() and base64_decode_fast() wrappers
- Update b2a_base64 and a2b_base64 to use fast path for complete groups
Performance gains (encode/decode speedup vs main, PGO builds):
             64 bytes    64K        1M
  Zen2:      1.1x/1.6x   1.6x/2.4x  1.4x/2.4x
  Zen4:      1.2x/1.7x   1.6x/3.0x  1.5x/3.0x
  M4:        1.3x/1.9x   2.3x/2.8x  2.4x/2.9x
  RPi5-32:   1.4x/1.4x   2.4x/2.0x  2.0x/1.9x
Additional SIMD implementations (NEON, AVX-512 VBMI) can achieve
+50% to +1500% further gains and are planned for follow-on work.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

@gpshead

@gpshead gpshead changed the title Optimize base64 encode and decode for an easy 2-3x performance win gh-124951: Optimize base64 encode and decode for an easy 2-3x performance win [no SIMD required]

Dec 29, 2025

Open

@gpshead gpshead changed the title gh-124951: Optimize base64 encode and decode for an easy 2-3x performance win [no SIMD required] gh-124951: Optimize base64 encode and decode for an easy 2-3x speedup [no SIMD required]

Dec 29, 2025

@gpshead gpshead changed the title gh-124951: Optimize base64 encode and decode for an easy 2-3x speedup [no SIMD required] gh-124951: Optimize base64 encode & decode for an easy 2-3x speedup [no SIMD]

Dec 29, 2025
MSVC doesn't support forward declarations of arrays without explicit
size. Move the table definition before the inline functions that use
it, eliminating the need for a forward declaration.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

picnixz

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>

@gpshead

gpshead marked this pull request as ready for review

December 29, 2025 01:08

@gpshead

@gpshead

Add Py_ALIGNED(64) to both lookup tables to ensure each fits
within a single L1 cache line, reducing potential cache misses
during encoding/decoding loops.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Replace hardcoded '=' characters with the BASE64_PAD macro
for consistency with the rest of the codebase.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

@gpshead

gpshead

Merged

@gpshead

serhiy-storchaka

Merged

Address review feedback from serhiy-storchaka: the fast path was doing
two checks per group - an explicit PAD comparison and the invalid char
check in base64_decode_quad().
Change PAD's table entry from 0 to 64 so the existing (v0|v1|v2|v3)&0xc0
check catches it, eliminating 4 comparisons per group.
The slow path is unaffected since it checks for PAD character before
the table lookup.
Decode is ~16% faster at 64K (1.62 GB/s → 1.88 GB/s).
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Suggested by serhiy-storchaka: replace index math (in + i*3, out + i*4)
with pointer increments. Encode is ~7% faster at 64K (2.11 → 2.25 GB/s).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

@gpshead

serhiy-storchaka

thunder-coding pushed a commit to thunder-coding/cpython that referenced this pull request

Feb 15, 2026
…edup [no SIMD] (pythonGH-143262)
Optimize base64 encoding/decoding by eliminating loop-carried dependencies. Key changes:
- Add `base64_encode_trio()` and `base64_decode_quad()` helper functions that process complete groups independently
- Add `base64_encode_fast()` and `base64_decode_fast()` wrappers
- Update `b2a_base64` and `a2b_base64` to use fast path for complete groups
Performance gains (encode/decode speedup vs main, PGO builds):
```
             64 bytes    64K        1M
  Zen2:      1.2x/1.8x   1.7x/2.8x  1.5x/2.8x
  Zen4:      1.2x/1.7x   1.6x/3.0x  1.5x/3.0x  [old data, likely faster]
  M4:        1.3x/1.9x   2.3x/2.8x  2.4x/2.9x  [old data, likely faster]
  RPi5-32:   1.2x/1.2x   2.4x/2.4x  2.0x/2.1x
```
Based on my exploratory work done in python/cpython@ main...gpshead:cpython:claude/vectorize-base64-c-S7Hku 
See PR and issue for further thoughts on sometimes MUCH faster SIMD vectorized versions of this.

Read the original on github.com ↗