Skip to content

gh-87613: Use AC VC for io.BytesIO - #160855

Open
cmaloney wants to merge 1 commit into
python:mainfrom
cmaloney:ac_vc_bytesio
Open

cmaloney wants to merge 1 commit into
python:mainfrom
cmaloney:ac_vc_bytesio

Conversation

@cmaloney

@cmaloney cmaloney commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

BytesIO is commonly constructed in the test suite and gets significantly faster to construct. Argument error messages are unchanged.

pyperf microbenchmark (PGO+LTO, run serially):

Benchmark base bytesio
BytesIO(bytes) 54.2 ns 27.0 ns: 2.01x faster
BytesIO(bytearray) 76.7 ns 38.6 ns: 1.99x faster
BytesIO(initial_bytes=bytes) 56.5 ns 34.8 ns: 1.63x faster
BytesIO() 40.9 ns 25.4 ns: 1.61x faster
Geometric mean (ref) 1.48x faster

Benchmark hidden because not significant (2): BytesIO.__new__, subclass(bytes)

Benchmark code:

"""BytesIO() construction: AC @vectorcall vs tp_new + tp_init."""
import pyperf

runner = pyperf.Runner()

setup = "from io import BytesIO; b = b'abcdefgh'"
runner.timeit('BytesIO()', 'BytesIO()', setup)
runner.timeit('BytesIO(bytes)', 'BytesIO(b)', setup)
runner.timeit('BytesIO(bytearray)', 'BytesIO(x)', setup + '; x = bytearray(b)')
runner.timeit('BytesIO(initial_bytes=bytes)', 'BytesIO(initial_bytes=b)', setup)
runner.timeit('subclass(bytes)', 'S(b)', setup + '\nclass S(BytesIO): pass')
runner.timeit('BytesIO.__new__', 'new(BytesIO)',
              setup + '; new = BytesIO.__new__')

BytesIO is commonly constructed in the test suite and gets significantly
faster to construct. Argument error messages are unchanged.

pyperf microbenchmark (PGO+LTO, run serially):

| Benchmark                    | base    | bytesio               |
|------------------------------|:-------:|:---------------------:|
| BytesIO(bytes)               | 54.2 ns | 27.0 ns: 2.01x faster |
| BytesIO(bytearray)           | 76.7 ns | 38.6 ns: 1.99x faster |
| BytesIO(initial_bytes=bytes) | 56.5 ns | 34.8 ns: 1.63x faster |
| BytesIO()                    | 40.9 ns | 25.4 ns: 1.61x faster |
| Geometric mean               | (ref)   | 1.48x faster          |

Benchmark hidden because not significant (2): `BytesIO.__new__`,
subclass(bytes)

Benchmark code:

```python
"""BytesIO() construction: AC @vectorcall vs tp_new + tp_init."""
import pyperf

runner = pyperf.Runner()

setup = "from io import BytesIO; b = b'abcdefgh'"
runner.timeit('BytesIO()', 'BytesIO()', setup)
runner.timeit('BytesIO(bytes)', 'BytesIO(b)', setup)
runner.timeit('BytesIO(bytearray)', 'BytesIO(x)', setup + '; x = bytearray(b)')
runner.timeit('BytesIO(initial_bytes=bytes)', 'BytesIO(initial_bytes=b)', setup)
runner.timeit('subclass(bytes)', 'S(b)', setup + '\nclass S(BytesIO): pass')
runner.timeit('BytesIO.__new__', 'new(BytesIO)',
              setup + '; new = BytesIO.__new__')
```

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting review skip news type-feature A feature request or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants