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

Skip to content

Commit 8be5bc2

Browse files
Keep a per-interprter cache.
1 parent 3cab144 commit 8be5bc2

File tree

1 file changed

+43
-17
lines changed

1 file changed

+43
-17
lines changed

Python/crossinterp.c

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -127,27 +127,52 @@ ensure_isolated_main(PyThreadState *tstate, struct sync_module *main)
127127
assert(_PyErr_Occurred(tstate));
128128
return -1;
129129
}
130-
131-
// It wasn't already loaded from file.
132-
PyObject *loaded = PyModule_NewObject(&_Py_ID(__main__));
133-
if (loaded == NULL) {
134-
goto error;
130+
PyObject *loaded = NULL;
131+
132+
// Try the per-interpreter cache for the loaded module.
133+
// XXX Store it in sys.modules?
134+
PyObject *interpns = PyInterpreterState_GetDict(tstate->interp);
135+
assert(interpns != NULL);
136+
PyObject *key = PyUnicode_FromString("CACHED_MODULE_NS___main__");
137+
if (key == NULL) {
138+
// It's probably unrecoverable, so don't bother caching the error.
139+
Py_DECREF(mod);
140+
return -1;
135141
}
136-
PyObject *ns = _PyModule_GetDict(loaded);
137-
138-
// We don't want to trigger "if __name__ == '__main__':",
139-
// so we use a bogus module name.
140-
PyObject *loaded_ns =
141-
runpy_run_path(main->filename, "<fake __main__>");
142-
if (loaded_ns == NULL) {
143-
goto error;
142+
else if (PyDict_GetItemRef(interpns, key, &loaded) < 0) {
143+
// It's probably unrecoverable, so don't bother caching the error.
144+
Py_DECREF(mod);
145+
Py_DECREF(key);
146+
return -1;
144147
}
145-
int res = PyDict_Update(ns, loaded_ns);
146-
Py_DECREF(loaded_ns);
147-
if (res < 0) {
148-
goto error;
148+
else if (loaded == NULL) {
149+
// It wasn't already loaded from file.
150+
loaded = PyModule_NewObject(&_Py_ID(__main__));
151+
if (loaded == NULL) {
152+
goto error;
153+
}
154+
PyObject *ns = _PyModule_GetDict(loaded);
155+
156+
// We don't want to trigger "if __name__ == '__main__':",
157+
// so we use a bogus module name.
158+
PyObject *loaded_ns =
159+
runpy_run_path(main->filename, "<fake __main__>");
160+
if (loaded_ns == NULL) {
161+
goto error;
162+
}
163+
int res = PyDict_Update(ns, loaded_ns);
164+
Py_DECREF(loaded_ns);
165+
if (res < 0) {
166+
goto error;
167+
}
168+
169+
// Set the per-interpreter cache entry.
170+
if (PyDict_SetItem(interpns, key, loaded) < 0) {
171+
goto error;
172+
}
149173
}
150174

175+
Py_DECREF(key);
151176
main->cached = (struct sync_module_result){
152177
.module = mod,
153178
.loaded = loaded,
@@ -158,6 +183,7 @@ ensure_isolated_main(PyThreadState *tstate, struct sync_module *main)
158183
sync_module_capture_exc(tstate, main);
159184
Py_XDECREF(loaded);
160185
Py_DECREF(mod);
186+
Py_XDECREF(key);
161187
return -1;
162188
}
163189

0 commit comments

Comments
 (0)