diff --git a/Misc/NEWS.d/next/Library/2026-10-07-02-29-45.gh-issue-158897.jH3FwQ.rst b/Misc/NEWS.d/next/Library/2026-10-07-02-29-45.gh-issue-158897.jH3FwQ.rst new file mode 100644 index 00000000000000..4524077daefe9a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-07-02-29-45.gh-issue-158897.jH3FwQ.rst @@ -0,0 +1,5 @@ +Optimize :meth:`!io.BufferedReader.readline` when lines are close to the +buffer size (128 kB by default) or longer than the buffer size. Replace the +C loop searching for the newline byte in the buffer with a :c:func:`!memchr` +call which is more efficient. In the good case, it makes ``readline()`` up to +4x faster! Patch by Victor Stinner. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index d6318af1263d9c..44c3f56caee18b 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1280,16 +1280,14 @@ _buffered_readline(buffered *self, Py_ssize_t limit) n = limit; } start = self->buffer; - const char *end = start + n; - s = start; - while (s < end) { - if (*s++ == '\n') { - if (PyBytesWriter_WriteBytes(writer, start, s - start) < 0) { - goto error; - } - self->pos = s - start; - goto found; + const char *newline = memchr(start, '\n', n); + if (newline != NULL) { + n = newline - start + 1; + if (PyBytesWriter_WriteBytes(writer, start, n) < 0) { + goto error; } + self->pos = n; + goto found; } if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {