Skip to content

Commit 133138a

Browse files
Issue #22557: Now importing already imported modules is up to 2.5 times faster.
1 parent cde03fa commit 133138a

File tree

6 files changed

+238
-246
lines changed

6 files changed

+238
-246
lines changed

Include/pystate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ typedef struct _is {
4141
#endif
4242

4343
PyObject *builtins_copy;
44+
PyObject *import_func;
4445
} PyInterpreterState;
4546
#endif
4647

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.6.0 alpha 4
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #22557: Now importing already imported modules is up to 2.5 times faster.
14+
1315
- Issue #17596: Include <wincrypt.h> to help with Min GW building.
1416

1517
- Issue #27507: Add integer overflow check in bytearray.extend(). Patch by

Python/ceval.c

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ static int maybe_call_line_trace(Py_tracefunc, PyObject *,
139139
PyThreadState *, PyFrameObject *, int *, int *, int *);
140140

141141
static PyObject * cmp_outcome(int, PyObject *, PyObject *);
142+
static PyObject * import_name(PyFrameObject *, PyObject *, PyObject *, PyObject *);
142143
static PyObject * import_from(PyObject *, PyObject *);
143144
static int import_all_from(PyObject *, PyObject *);
144145
static void format_exc_check_arg(PyObject *, const char *, PyObject *);
@@ -2808,37 +2809,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
28082809
}
28092810

28102811
TARGET(IMPORT_NAME) {
2811-
_Py_IDENTIFIER(__import__);
28122812
PyObject *name = GETITEM(names, oparg);
2813-
PyObject *func = _PyDict_GetItemId(f->f_builtins, &PyId___import__);
2814-
PyObject *from, *level, *args, *res;
2815-
if (func == NULL) {
2816-
PyErr_SetString(PyExc_ImportError,
2817-
"__import__ not found");
2818-
goto error;
2819-
}
2820-
Py_INCREF(func);
2821-
from = POP();
2822-
level = TOP();
2823-
args = PyTuple_Pack(5,
2824-
name,
2825-
f->f_globals,
2826-
f->f_locals == NULL ?
2827-
Py_None : f->f_locals,
2828-
from,
2829-
level);
2830-
Py_DECREF(level);
2831-
Py_DECREF(from);
2832-
if (args == NULL) {
2833-
Py_DECREF(func);
2834-
STACKADJ(-1);
2835-
goto error;
2836-
}
2813+
PyObject *fromlist = POP();
2814+
PyObject *level = TOP();
2815+
PyObject *res;
28372816
READ_TIMESTAMP(intr0);
2838-
res = PyEval_CallObject(func, args);
2817+
res = import_name(f, name, fromlist, level);
2818+
Py_DECREF(level);
2819+
Py_DECREF(fromlist);
28392820
READ_TIMESTAMP(intr1);
2840-
Py_DECREF(args);
2841-
Py_DECREF(func);
28422821
SET_TOP(res);
28432822
if (res == NULL)
28442823
goto error;
@@ -5158,6 +5137,50 @@ cmp_outcome(int op, PyObject *v, PyObject *w)
51585137
return v;
51595138
}
51605139

5140+
static PyObject *
5141+
import_name(PyFrameObject *f, PyObject *name, PyObject *fromlist, PyObject *level)
5142+
{
5143+
_Py_IDENTIFIER(__import__);
5144+
PyObject *import_func, *args, *res;
5145+
5146+
import_func = _PyDict_GetItemId(f->f_builtins, &PyId___import__);
5147+
if (import_func == NULL) {
5148+
PyErr_SetString(PyExc_ImportError, "__import__ not found");
5149+
return NULL;
5150+
}
5151+
5152+
/* Fast path for not overloaded __import__. */
5153+
if (import_func == PyThreadState_GET()->interp->import_func) {
5154+
int ilevel = _PyLong_AsInt(level);
5155+
if (ilevel == -1 && PyErr_Occurred()) {
5156+
return NULL;
5157+
}
5158+
res = PyImport_ImportModuleLevelObject(
5159+
name,
5160+
f->f_globals,
5161+
f->f_locals == NULL ? Py_None : f->f_locals,
5162+
fromlist,
5163+
ilevel);
5164+
return res;
5165+
}
5166+
5167+
Py_INCREF(import_func);
5168+
args = PyTuple_Pack(5,
5169+
name,
5170+
f->f_globals,
5171+
f->f_locals == NULL ? Py_None : f->f_locals,
5172+
fromlist,
5173+
level);
5174+
if (args == NULL) {
5175+
Py_DECREF(import_func);
5176+
return NULL;
5177+
}
5178+
res = PyEval_CallObject(import_func, args);
5179+
Py_DECREF(args);
5180+
Py_DECREF(import_func);
5181+
return res;
5182+
}
5183+
51615184
static PyObject *
51625185
import_from(PyObject *v, PyObject *name)
51635186
{

0 commit comments

Comments
 (0)