Commit 393f705f authored by Nadeem Vawda's avatar Nadeem Vawda

Issue #13159: Replace FileIO's quadratic-time buffer growth algorithm with a linear-time one.

Also fix the builtin file class and the bz2 module, which used the same algorithm.
parent 0992a60d
...@@ -229,6 +229,9 @@ Library ...@@ -229,6 +229,9 @@ Library
Extension Modules Extension Modules
----------------- -----------------
- Issue #13159: FileIO, BZ2File, and the built-in file class now use a
linear-time buffer growth strategy instead of a quadratic one.
- Issue #13070: Fix a crash when a TextIOWrapper caught in a reference cycle - Issue #13070: Fix a crash when a TextIOWrapper caught in a reference cycle
would be finalized after the reference to its underlying BufferedRWPair's would be finalized after the reference to its underlying BufferedRWPair's
writer got cleared by the GC. writer got cleared by the GC.
......
...@@ -42,12 +42,6 @@ ...@@ -42,12 +42,6 @@
#define SMALLCHUNK BUFSIZ #define SMALLCHUNK BUFSIZ
#endif #endif
#if SIZEOF_INT < 4
#define BIGCHUNK (512 * 32)
#else
#define BIGCHUNK (512 * 1024)
#endif
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
int fd; int fd;
...@@ -528,15 +522,10 @@ new_buffersize(fileio *self, size_t currentsize) ...@@ -528,15 +522,10 @@ new_buffersize(fileio *self, size_t currentsize)
} }
} }
#endif #endif
if (currentsize > SMALLCHUNK) { /* Expand the buffer by an amount proportional to the current size,
/* Keep doubling until we reach BIGCHUNK; giving us amortized linear-time behavior. Use a less-than-double
then keep adding BIGCHUNK. */ growth factor to avoid excessive allocation. */
if (currentsize <= BIGCHUNK) return currentsize + (currentsize >> 3) + 6;
return currentsize + currentsize;
else
return currentsize + BIGCHUNK;
}
return currentsize + SMALLCHUNK;
} }
static PyObject * static PyObject *
......
...@@ -224,25 +224,14 @@ Util_CatchBZ2Error(int bzerror) ...@@ -224,25 +224,14 @@ Util_CatchBZ2Error(int bzerror)
#define SMALLCHUNK BUFSIZ #define SMALLCHUNK BUFSIZ
#endif #endif
#if SIZEOF_INT < 4
#define BIGCHUNK (512 * 32)
#else
#define BIGCHUNK (512 * 1024)
#endif
/* This is a hacked version of Python's fileobject.c:new_buffersize(). */ /* This is a hacked version of Python's fileobject.c:new_buffersize(). */
static size_t static size_t
Util_NewBufferSize(size_t currentsize) Util_NewBufferSize(size_t currentsize)
{ {
if (currentsize > SMALLCHUNK) { /* Expand the buffer by an amount proportional to the current size,
/* Keep doubling until we reach BIGCHUNK; giving us amortized linear-time behavior. Use a less-than-double
then keep adding BIGCHUNK. */ growth factor to avoid excessive allocation. */
if (currentsize <= BIGCHUNK) return currentsize + (currentsize >> 3) + 6;
return currentsize + currentsize;
else
return currentsize + BIGCHUNK;
}
return currentsize + SMALLCHUNK;
} }
/* This is a hacked version of Python's fileobject.c:get_line(). */ /* This is a hacked version of Python's fileobject.c:get_line(). */
......
...@@ -992,12 +992,6 @@ file_isatty(PyFileObject *f) ...@@ -992,12 +992,6 @@ file_isatty(PyFileObject *f)
#define SMALLCHUNK BUFSIZ #define SMALLCHUNK BUFSIZ
#endif #endif
#if SIZEOF_INT < 4
#define BIGCHUNK (512 * 32)
#else
#define BIGCHUNK (512 * 1024)
#endif
static size_t static size_t
new_buffersize(PyFileObject *f, size_t currentsize) new_buffersize(PyFileObject *f, size_t currentsize)
{ {
...@@ -1026,15 +1020,10 @@ new_buffersize(PyFileObject *f, size_t currentsize) ...@@ -1026,15 +1020,10 @@ new_buffersize(PyFileObject *f, size_t currentsize)
/* Add 1 so if the file were to grow we'd notice. */ /* Add 1 so if the file were to grow we'd notice. */
} }
#endif #endif
if (currentsize > SMALLCHUNK) { /* Expand the buffer by an amount proportional to the current size,
/* Keep doubling until we reach BIGCHUNK; giving us amortized linear-time behavior. Use a less-than-double
then keep adding BIGCHUNK. */ growth factor to avoid excessive allocation. */
if (currentsize <= BIGCHUNK) return currentsize + (currentsize >> 3) + 6;
return currentsize + currentsize;
else
return currentsize + BIGCHUNK;
}
return currentsize + SMALLCHUNK;
} }
#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN #if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment