Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 72d6a13

Browse files
committed
Merge #13159: Replace FileIO's quadratic-time buffer growth algorithm with a linear-time one.
Also fix the bz2 module, which suffered from the same problem.
2 parents 55c9911 + d41a98b commit 72d6a13

3 files changed

Lines changed: 11 additions & 27 deletions

File tree

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,9 @@ Tools/Demos
13421342
Extension Modules
13431343
-----------------
13441344

1345+
- Issue #13159: FileIO and BZ2Compressor/BZ2Decompressor now use a linear-time
1346+
buffer growth strategy instead of a quadratic-time one.
1347+
13451348
- Issue #10141: socket: Add SocketCAN (PF_CAN) support. Initial patch by
13461349
Matthias Fuchs, updated by Tiago Gonçalves.
13471350

Modules/_bz2module.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,22 +116,14 @@ catch_bz2_error(int bzerror)
116116
#define SMALLCHUNK BUFSIZ
117117
#endif
118118

119-
#if SIZEOF_INT < 4
120-
#define BIGCHUNK (512 * 32)
121-
#else
122-
#define BIGCHUNK (512 * 1024)
123-
#endif
124-
125119
static int
126120
grow_buffer(PyObject **buf)
127121
{
122+
/* Expand the buffer by an amount proportional to the current size,
123+
giving us amortized linear-time behavior. Use a less-than-double
124+
growth factor to avoid excessive allocation. */
128125
size_t size = PyBytes_GET_SIZE(*buf);
129-
if (size <= SMALLCHUNK)
130-
return _PyBytes_Resize(buf, size + SMALLCHUNK);
131-
else if (size <= BIGCHUNK)
132-
return _PyBytes_Resize(buf, size * 2);
133-
else
134-
return _PyBytes_Resize(buf, size + BIGCHUNK);
126+
return _PyBytes_Resize(buf, size + (size >> 3) + 6);
135127
}
136128

137129

Modules/_io/fileio.c

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@
4343
#define SMALLCHUNK BUFSIZ
4444
#endif
4545

46-
#if SIZEOF_INT < 4
47-
#define BIGCHUNK (512 * 32)
48-
#else
49-
#define BIGCHUNK (512 * 1024)
50-
#endif
51-
5246
typedef struct {
5347
PyObject_HEAD
5448
int fd;
@@ -572,15 +566,10 @@ new_buffersize(fileio *self, size_t currentsize
572566
}
573567
}
574568
#endif
575-
if (currentsize > SMALLCHUNK) {
576-
/* Keep doubling until we reach BIGCHUNK;
577-
then keep adding BIGCHUNK. */
578-
if (currentsize <= BIGCHUNK)
579-
return currentsize + currentsize;
580-
else
581-
return currentsize + BIGCHUNK;
582-
}
583-
return currentsize + SMALLCHUNK;
569+
/* Expand the buffer by an amount proportional to the current size,
570+
giving us amortized linear-time behavior. Use a less-than-double
571+
growth factor to avoid excessive allocation. */
572+
return currentsize + (currentsize >> 3) + 6;
584573
}
585574

586575
static PyObject *

0 commit comments

Comments
 (0)