]> granicus.if.org Git - python/commitdiff
Variant of SF patch 103252: Startup optimize: read *.pyc as string, not with getc().
authorTim Peters <tim.peters@gmail.com>
Thu, 18 Jan 2001 04:39:16 +0000 (04:39 +0000)
committerTim Peters <tim.peters@gmail.com>
Thu, 18 Jan 2001 04:39:16 +0000 (04:39 +0000)
Misc/ACKS
Python/marshal.c

index 6c90fd4d9192c4a546db2f1710b8f9d6842f304b..2a15aed382be937f628c2bd389657e57175bd381 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -179,6 +179,7 @@ Greg Humphreys
 Jeremy Hylton
 John Interrante
 Ben Jackson
+Paul Jackson
 Jack Jansen
 Bill Janssen
 Drew Jenkins
index a9b3ed1653de07a259d1b486b82fba9ea64c1505..684a8b4c08a8738cd3e75640611ede2ea76711ed 100644 (file)
@@ -606,16 +606,63 @@ PyMarshal_ReadLongFromFile(FILE *fp)
        return r_long(&rf);
 }
 
+#ifdef HAVE_FSTAT
+/* Return size of file in bytes; < 0 if unknown. */
+static off_t
+getfilesize(FILE *fp)
+{
+       struct stat st;
+       if (fstat(fileno(fp), &st) != 0)
+               return -1;
+       else
+               return st.st_size;
+}
+#endif
+/* If we can get the size of the file up-front, and it's reasonably small,
+ * read it in one gulp and delegate to ...FromString() instead.  Much quicker
+ * than reading a byte at a time from file; speeds .pyc imports.
+ */
 PyObject *
 PyMarshal_ReadObjectFromFile(FILE *fp)
 {
+/* 75% of 2.1's .pyc files can exploit SMALL_FILE_LIMIT.
+ * REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc.
+ */
+#define SMALL_FILE_LIMIT (1L << 14)
+#define REASONABLE_FILE_LIMIT (1L << 18)
        RFILE rf;
+#ifdef HAVE_FSTAT
+       off_t filesize;
+#endif
        if (PyErr_Occurred()) {
                fprintf(stderr, "XXX rd_object called with exception set\n");
                return NULL;
        }
+#ifdef HAVE_FSTAT
+       filesize = getfilesize(fp);
+       if (filesize > 0) {
+               char buf[SMALL_FILE_LIMIT];
+               char* pBuf = NULL;
+               if (filesize <= SMALL_FILE_LIMIT)
+                       pBuf = buf;
+               else if (filesize <= REASONABLE_FILE_LIMIT)
+                       pBuf = (char *)PyMem_MALLOC(filesize);
+               if (pBuf != NULL) {
+                       PyObject* v;
+                       size_t n = fread(pBuf, 1, filesize, fp);
+                       v = PyMarshal_ReadObjectFromString(pBuf, n);
+                       if (pBuf != buf)
+                               PyMem_FREE(pBuf);
+                       return v;
+               }
+               
+       }
+#endif
        rf.fp = fp;
        return r_object(&rf);
+#undef SMALL_FILE_LIMIT
+#undef REASONABLE_FILE_LIMIT
 }
 
 PyObject *