]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-140135: Use `PyBytesWriter` in `io.RawIOBase.readall()`; 4x faster (#140139)
authorMaurycy Pawłowski-Wieroński <5383+maurycy@users.noreply.github.com>
Wed, 15 Oct 2025 14:04:17 +0000 (16:04 +0200)
committerGitHub <noreply@github.com>
Wed, 15 Oct 2025 14:04:17 +0000 (14:04 +0000)
Misc/NEWS.d/next/Library/2025-10-15-02-26-50.gh-issue-140135.54JYfM.rst [new file with mode: 0644]
Modules/_io/iobase.c

diff --git a/Misc/NEWS.d/next/Library/2025-10-15-02-26-50.gh-issue-140135.54JYfM.rst b/Misc/NEWS.d/next/Library/2025-10-15-02-26-50.gh-issue-140135.54JYfM.rst
new file mode 100644 (file)
index 0000000..8d5a76a
--- /dev/null
@@ -0,0 +1,2 @@
+Speed up :meth:`io.RawIOBase.readall` by using PyBytesWriter API (about 4x
+faster)
index aa373f6fdcb9d9d562ad780e5312017385a41915..acadbcc4d59c3838e1e82804063f3360da26c934 100644 (file)
@@ -962,12 +962,10 @@ static PyObject *
 _io__RawIOBase_readall_impl(PyObject *self)
 /*[clinic end generated code: output=1987b9ce929425a0 input=688874141213622a]*/
 {
-    int r;
-    PyObject *chunks = PyList_New(0);
-    PyObject *result;
-
-    if (chunks == NULL)
+    PyBytesWriter *writer = PyBytesWriter_Create(0);
+    if (writer == NULL) {
         return NULL;
+    }
 
     while (1) {
         PyObject *data = _PyObject_CallMethod(self, &_Py_ID(read),
@@ -978,21 +976,21 @@ _io__RawIOBase_readall_impl(PyObject *self)
             if (_PyIO_trap_eintr()) {
                 continue;
             }
-            Py_DECREF(chunks);
+            PyBytesWriter_Discard(writer);
             return NULL;
         }
         if (data == Py_None) {
-            if (PyList_GET_SIZE(chunks) == 0) {
-                Py_DECREF(chunks);
+            if (PyBytesWriter_GetSize(writer) == 0) {
+                PyBytesWriter_Discard(writer);
                 return data;
             }
             Py_DECREF(data);
             break;
         }
         if (!PyBytes_Check(data)) {
-            Py_DECREF(chunks);
             Py_DECREF(data);
             PyErr_SetString(PyExc_TypeError, "read() should return bytes");
+            PyBytesWriter_Discard(writer);
             return NULL;
         }
         if (PyBytes_GET_SIZE(data) == 0) {
@@ -1000,16 +998,16 @@ _io__RawIOBase_readall_impl(PyObject *self)
             Py_DECREF(data);
             break;
         }
-        r = PyList_Append(chunks, data);
-        Py_DECREF(data);
-        if (r < 0) {
-            Py_DECREF(chunks);
+        if (PyBytesWriter_WriteBytes(writer,
+                                     PyBytes_AS_STRING(data),
+                                     PyBytes_GET_SIZE(data)) < 0) {
+            Py_DECREF(data);
+            PyBytesWriter_Discard(writer);
             return NULL;
         }
+        Py_DECREF(data);
     }
-    result = PyBytes_Join((PyObject *)&_Py_SINGLETON(bytes_empty), chunks);
-    Py_DECREF(chunks);
-    return result;
+    return PyBytesWriter_Finish(writer);
 }
 
 static PyObject *