Skip to content

Commit 1610807

Browse files
authored
gh-158897: Optimize io.BufferedReader.readline() by calling memchr() (#158944)
Optimize 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 memchr() call which is more efficient. In the good case, it makes readline() up to 4x faster!
1 parent c120cae commit 1610807

2 files changed

Lines changed: 12 additions & 9 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Optimize :meth:`!io.BufferedReader.readline` when lines are close to the
2+
buffer size (128 kB by default) or longer than the buffer size. Replace the
3+
C loop searching for the newline byte in the buffer with a :c:func:`!memchr`
4+
call which is more efficient. In the good case, it makes ``readline()`` up to
5+
4x faster! Patch by Victor Stinner.

‎Modules/_io/bufferedio.c‎

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,16 +1280,14 @@ _buffered_readline(buffered *self, Py_ssize_t limit)
12801280
n = limit;
12811281
}
12821282
start = self->buffer;
1283-
const char *end = start + n;
1284-
s = start;
1285-
while (s < end) {
1286-
if (*s++ == '\n') {
1287-
if (PyBytesWriter_WriteBytes(writer, start, s - start) < 0) {
1288-
goto error;
1289-
}
1290-
self->pos = s - start;
1291-
goto found;
1283+
const char *newline = memchr(start, '\n', n);
1284+
if (newline != NULL) {
1285+
n = newline - start + 1;
1286+
if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {
1287+
goto error;
12921288
}
1289+
self->pos = n;
1290+
goto found;
12931291
}
12941292

12951293
if (PyBytesWriter_WriteBytes(writer, start, n) < 0) {

0 commit comments

Comments
 (0)