Commit a2ace6ae authored by Guido van Rossum's avatar Guido van Rossum

Charles G Waldman:

Follow a suggestion in an /*XXX*/ comment [in com_add()] to speed up
compilation by using supplemental dictionaries to keep track of names
and constants, eliminating quadratic behavior.  With this patch in
place, the time to import a 5000-line file with lots of constants [at
the global level] is reduced from 20 seconds to under 3 on my system.
parent 3c3507fd
...@@ -301,7 +301,9 @@ PyCode_New(argcount, nlocals, stacksize, flags, ...@@ -301,7 +301,9 @@ PyCode_New(argcount, nlocals, stacksize, flags,
struct compiling { struct compiling {
PyObject *c_code; /* string */ PyObject *c_code; /* string */
PyObject *c_consts; /* list of objects */ PyObject *c_consts; /* list of objects */
PyObject *c_const_dict; /* inverse of c_consts */
PyObject *c_names; /* list of strings (names) */ PyObject *c_names; /* list of strings (names) */
PyObject *c_name_dict; /* inverse of c_names */
PyObject *c_globals; /* dictionary (value=None) */ PyObject *c_globals; /* dictionary (value=None) */
PyObject *c_locals; /* dictionary (value=localID) */ PyObject *c_locals; /* dictionary (value=localID) */
PyObject *c_varnames; /* list (inverse of c_locals) */ PyObject *c_varnames; /* list (inverse of c_locals) */
...@@ -403,7 +405,7 @@ static void com_addint Py_PROTO((struct compiling *, int)); ...@@ -403,7 +405,7 @@ static void com_addint Py_PROTO((struct compiling *, int));
static void com_addoparg Py_PROTO((struct compiling *, int, int)); static void com_addoparg Py_PROTO((struct compiling *, int, int));
static void com_addfwref Py_PROTO((struct compiling *, int, int *)); static void com_addfwref Py_PROTO((struct compiling *, int, int *));
static void com_backpatch Py_PROTO((struct compiling *, int)); static void com_backpatch Py_PROTO((struct compiling *, int));
static int com_add Py_PROTO((struct compiling *, PyObject *, PyObject *)); static int com_add Py_PROTO((struct compiling *, PyObject *, PyObject *, PyObject *));
static int com_addconst Py_PROTO((struct compiling *, PyObject *)); static int com_addconst Py_PROTO((struct compiling *, PyObject *));
static int com_addname Py_PROTO((struct compiling *, PyObject *)); static int com_addname Py_PROTO((struct compiling *, PyObject *));
static void com_addopname Py_PROTO((struct compiling *, int, node *)); static void com_addopname Py_PROTO((struct compiling *, int, node *));
...@@ -421,22 +423,27 @@ com_init(c, filename) ...@@ -421,22 +423,27 @@ com_init(c, filename)
struct compiling *c; struct compiling *c;
char *filename; char *filename;
{ {
memset((void *)c, '\0', sizeof(struct compiling));
if ((c->c_code = PyString_FromStringAndSize((char *)NULL, if ((c->c_code = PyString_FromStringAndSize((char *)NULL,
1000)) == NULL) 1000)) == NULL)
goto fail_3; goto fail;
if ((c->c_consts = PyList_New(0)) == NULL) if ((c->c_consts = PyList_New(0)) == NULL)
goto fail_2; goto fail;
if ((c->c_const_dict = PyDict_New()) == NULL)
goto fail;
if ((c->c_names = PyList_New(0)) == NULL) if ((c->c_names = PyList_New(0)) == NULL)
goto fail_1; goto fail;
if ((c->c_name_dict = PyDict_New()) == NULL)
goto fail;
if ((c->c_globals = PyDict_New()) == NULL) if ((c->c_globals = PyDict_New()) == NULL)
goto fail_0; goto fail;
if ((c->c_locals = PyDict_New()) == NULL) if ((c->c_locals = PyDict_New()) == NULL)
goto fail_00; goto fail;
if ((c->c_varnames = PyList_New(0)) == NULL) if ((c->c_varnames = PyList_New(0)) == NULL)
goto fail_000; goto fail;
if ((c->c_lnotab = PyString_FromStringAndSize((char *)NULL, if ((c->c_lnotab = PyString_FromStringAndSize((char *)NULL,
1000)) == NULL) 1000)) == NULL)
goto fail_0000; goto fail;
c->c_nlocals = 0; c->c_nlocals = 0;
c->c_argcount = 0; c->c_argcount = 0;
c->c_flags = 0; c->c_flags = 0;
...@@ -458,19 +465,8 @@ com_init(c, filename) ...@@ -458,19 +465,8 @@ com_init(c, filename)
c-> c_lnotab_next = 0; c-> c_lnotab_next = 0;
return 1; return 1;
fail_0000: fail:
Py_DECREF(c->c_varnames); com_free(c);
fail_000:
Py_DECREF(c->c_locals);
fail_00:
Py_DECREF(c->c_globals);
fail_0:
Py_DECREF(c->c_names);
fail_1:
Py_DECREF(c->c_consts);
fail_2:
Py_DECREF(c->c_code);
fail_3:
return 0; return 0;
} }
...@@ -480,7 +476,9 @@ com_free(c) ...@@ -480,7 +476,9 @@ com_free(c)
{ {
Py_XDECREF(c->c_code); Py_XDECREF(c->c_code);
Py_XDECREF(c->c_consts); Py_XDECREF(c->c_consts);
Py_XDECREF(c->c_const_dict);
Py_XDECREF(c->c_names); Py_XDECREF(c->c_names);
Py_XDECREF(c->c_name_dict);
Py_XDECREF(c->c_globals); Py_XDECREF(c->c_globals);
Py_XDECREF(c->c_locals); Py_XDECREF(c->c_locals);
Py_XDECREF(c->c_varnames); Py_XDECREF(c->c_varnames);
...@@ -665,24 +663,39 @@ com_backpatch(c, anchor) ...@@ -665,24 +663,39 @@ com_backpatch(c, anchor)
/* Handle literals and names uniformly */ /* Handle literals and names uniformly */
static int static int
com_add(c, list, v) com_add(c, list, dict, v)
struct compiling *c; struct compiling *c;
PyObject *list; PyObject *list;
PyObject *dict;
PyObject *v; PyObject *v;
{ {
int n = PyList_Size(list); PyObject *w, *t, *np=NULL;
int i; long n;
/* XXX This is quadratic in the number of names per compilation unit.
XXX Should use a dictionary. */ t = Py_BuildValue("(OO)", v, v->ob_type);
for (i = n; --i >= 0; ) { if (t == NULL)
PyObject *w = PyList_GetItem(list, i); goto fail;
if (v->ob_type == w->ob_type && PyObject_Compare(v, w) == 0) w = PyDict_GetItem(dict, t);
return i; if (w != NULL) {
} n = PyInt_AsLong(w);
/* Check for error from PyObject_Compare */ } else {
if (PyErr_Occurred() || PyList_Append(list, v) != 0) n = PyList_Size(list);
c->c_errors++; np = PyInt_FromLong(n);
if (np == NULL)
goto fail;
if (PyList_Append(list, v) != 0)
goto fail;
if (PyDict_SetItem(dict, t, np) != 0)
goto fail;
Py_DECREF(np);
}
Py_DECREF(t);
return n; return n;
fail:
Py_XDECREF(np);
Py_XDECREF(t);
c->c_errors++;
return 0;
} }
static int static int
...@@ -690,7 +703,7 @@ com_addconst(c, v) ...@@ -690,7 +703,7 @@ com_addconst(c, v)
struct compiling *c; struct compiling *c;
PyObject *v; PyObject *v;
{ {
return com_add(c, c->c_consts, v); return com_add(c, c->c_consts, c->c_const_dict, v);
} }
static int static int
...@@ -698,7 +711,7 @@ com_addname(c, v) ...@@ -698,7 +711,7 @@ com_addname(c, v)
struct compiling *c; struct compiling *c;
PyObject *v; PyObject *v;
{ {
return com_add(c, c->c_names, v); return com_add(c, c->c_names, c->c_name_dict, v);
} }
#ifdef PRIVATE_NAME_MANGLING #ifdef PRIVATE_NAME_MANGLING
......
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