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

Skip to content

Commit 0e6b7b5

Browse files
Issue #8745: Small speed up zipimport on Windows. Patch by Catalin Iacob.
1 parent 0cad7ec commit 0e6b7b5

3 files changed

Lines changed: 22 additions & 9 deletions

File tree

Lib/test/test_zipimport.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ def testZipImporterMethods(self):
196196
for name, (mtime, data) in files.items():
197197
zinfo = ZipInfo(name, time.localtime(mtime))
198198
zinfo.compress_type = self.compression
199+
zinfo.comment = b"spam"
199200
z.writestr(zinfo, data)
200201
z.close()
201202

@@ -245,6 +246,7 @@ def testZipImporterMethodsInSubDirectory(self):
245246
for name, (mtime, data) in files.items():
246247
zinfo = ZipInfo(name, time.localtime(mtime))
247248
zinfo.compress_type = self.compression
249+
zinfo.comment = b"eggs"
248250
z.writestr(zinfo, data)
249251
z.close()
250252

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ What's New in Python 3.4.0 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #8745: Small speed up zipimport on Windows. Patch by Catalin Iacob.
14+
1315
- Issue #5308: Raise ValueError when marshalling too large object (a sequence
1416
with size >= 2**31), instead of producing illegal marshal data.
1517

Modules/zipimport.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,7 @@ read_directory(PyObject *archive)
862862
long l, count;
863863
Py_ssize_t i;
864864
char name[MAXPATHLEN + 5];
865+
char dummy[8]; /* Buffer to read unused header values into */
865866
PyObject *nameobj = NULL;
866867
char *p, endof_central_dir[22];
867868
Py_ssize_t arc_offset; /* Absolute offset to start of the zip-archive. */
@@ -905,17 +906,23 @@ read_directory(PyObject *archive)
905906

906907
/* Start of Central Directory */
907908
count = 0;
909+
if (fseek(fp, header_offset, 0) == -1)
910+
goto file_error;
908911
for (;;) {
909912
PyObject *t;
910913
int err;
911914

912-
if (fseek(fp, header_offset, 0) == -1) /* Start of file header */
913-
goto fseek_error;
915+
/* Start of file header */
914916
l = PyMarshal_ReadLongFromFile(fp);
915917
if (l != 0x02014B50)
916918
break; /* Bad: Central Dir File Header */
917-
if (fseek(fp, header_offset + 8, 0) == -1)
918-
goto fseek_error;
919+
920+
/* On Windows, calling fseek to skip over the fields we don't use is
921+
slower than reading the data into a dummy buffer because fseek flushes
922+
stdio's internal buffers. See issue #8745. */
923+
if (fread(dummy, 1, 4, fp) != 4) /* Skip unused fields, avoid fseek */
924+
goto file_error;
925+
919926
flags = (unsigned short)PyMarshal_ReadShortFromFile(fp);
920927
compress = PyMarshal_ReadShortFromFile(fp);
921928
time = PyMarshal_ReadShortFromFile(fp);
@@ -924,11 +931,11 @@ read_directory(PyObject *archive)
924931
data_size = PyMarshal_ReadLongFromFile(fp);
925932
file_size = PyMarshal_ReadLongFromFile(fp);
926933
name_size = PyMarshal_ReadShortFromFile(fp);
927-
header_size = 46 + name_size +
934+
header_size = name_size +
928935
PyMarshal_ReadShortFromFile(fp) +
929936
PyMarshal_ReadShortFromFile(fp);
930-
if (fseek(fp, header_offset + 42, 0) == -1)
931-
goto fseek_error;
937+
if (fread(dummy, 1, 8, fp) != 8) /* Skip unused fields, avoid fseek */
938+
goto file_error;
932939
file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;
933940
if (name_size > MAXPATHLEN)
934941
name_size = MAXPATHLEN;
@@ -941,7 +948,9 @@ read_directory(PyObject *archive)
941948
p++;
942949
}
943950
*p = 0; /* Add terminating null byte */
944-
header_offset += header_size;
951+
for (; i < header_size; i++) /* Skip the rest of the header */
952+
if(getc(fp) == EOF) /* Avoid fseek */
953+
goto file_error;
945954

946955
bootstrap = 0;
947956
if (flags & 0x0800)
@@ -988,7 +997,7 @@ read_directory(PyObject *archive)
988997
PySys_FormatStderr("# zipimport: found %ld names in %R\n",
989998
count, archive);
990999
return files;
991-
fseek_error:
1000+
file_error:
9921001
fclose(fp);
9931002
Py_XDECREF(files);
9941003
Py_XDECREF(nameobj);

0 commit comments

Comments
 (0)