Skip to content

Commit 61fdee3

Browse files
cmaloneyclaude
andauthored
gh-87613: Use AC VC for io.BytesIO (#160855)
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 <noreply@anthropic.com>
1 parent eba2a21 commit 61fdee3

2 files changed

Lines changed: 70 additions & 7 deletions

File tree

‎Modules/_io/bytesio.c‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,7 @@ bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
11181118
}
11191119

11201120
/*[clinic input]
1121+
@vectorcall
11211122
@critical_section
11221123
_io.BytesIO.__init__
11231124
initial_bytes as initvalue: object(c_default="NULL") = b''
@@ -1127,7 +1128,7 @@ Buffered I/O implementation using an in-memory bytes buffer.
11271128

11281129
static int
11291130
_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
1130-
/*[clinic end generated code: output=65c0c51e24c5b621 input=3da5a74ee4c4f1ac]*/
1131+
/*[clinic end generated code: output=65c0c51e24c5b621 input=a6dc38082204df28]*/
11311132
{
11321133
if (FT_ATOMIC_LOAD_SSIZE_RELAXED(self->exports) > 0) {
11331134
PyErr_SetString(PyExc_BufferError,
@@ -1256,6 +1257,7 @@ static PyType_Slot bytesio_slots[] = {
12561257
{Py_tp_getset, bytesio_getsetlist},
12571258
{Py_tp_init, _io_BytesIO___init__},
12581259
{Py_tp_new, bytesio_new},
1260+
{Py_tp_vectorcall, _io_BytesIO_vectorcall},
12591261
{0, NULL},
12601262
};
12611263

‎Modules/_io/clinic/bytesio.c.h‎

Lines changed: 67 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)