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

Skip to content

Commit a872de5

Browse files
committed
Fixed issue #4533: File read operation was dreadfully slow
1 parent 7a259ca commit a872de5

2 files changed

Lines changed: 31 additions & 4 deletions

File tree

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ What's New in Python 3.1 alpha 0
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #4533: File read operation was dreadfully slow due to a slowly
16+
growing read buffer. Fixed by using the same growth rate algorithm as
17+
Python 2.x.
18+
1519

1620
Library
1721
-------

Modules/_fileio.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@
2727
#include <windows.h>
2828
#endif
2929

30+
#if BUFSIZ < (8*1024)
31+
#define SMALLCHUNK (8*1024)
32+
#elif (BUFSIZ >= (2 << 25))
33+
#error "unreasonable BUFSIZ > 64MB defined"
34+
#else
35+
#define SMALLCHUNK BUFSIZ
36+
#endif
37+
38+
#if SIZEOF_INT < 4
39+
#define BIGCHUNK (512 * 32)
40+
#else
41+
#define BIGCHUNK (512 * 1024)
42+
#endif
43+
3044
typedef struct {
3145
PyObject_HEAD
3246
int fd;
@@ -387,21 +401,30 @@ fileio_readinto(PyFileIOObject *self, PyObject *args)
387401
return PyLong_FromSsize_t(n);
388402
}
389403

390-
#define DEFAULT_BUFFER_SIZE (8*1024)
391-
392404
static PyObject *
393405
fileio_readall(PyFileIOObject *self)
394406
{
395407
PyObject *result;
396408
Py_ssize_t total = 0;
397409
int n;
398410

399-
result = PyBytes_FromStringAndSize(NULL, DEFAULT_BUFFER_SIZE);
411+
result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK);
400412
if (result == NULL)
401413
return NULL;
402414

403415
while (1) {
404-
Py_ssize_t newsize = total + DEFAULT_BUFFER_SIZE;
416+
Py_ssize_t newsize = (total < SMALLCHUNK) ? SMALLCHUNK : total;
417+
418+
/* Keep doubling until we reach BIGCHUNK;
419+
then keep adding BIGCHUNK. */
420+
if (newsize <= BIGCHUNK) {
421+
newsize += newsize;
422+
}
423+
else {
424+
/* NOTE: overflow impossible due to limits on BUFSIZ */
425+
newsize += BIGCHUNK;
426+
}
427+
405428
if (PyBytes_GET_SIZE(result) < newsize) {
406429
if (_PyBytes_Resize(&result, newsize) < 0) {
407430
if (total == 0) {

0 commit comments

Comments
 (0)