summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Fludkov <fludkov.me@gmail.com>2018-02-07 16:36:26 +0100
committerMikhail Fludkov <misha@pexip.com>2018-02-07 18:06:21 +0100
commit080e1a8e8c130a94b5662770621dea2ad1646b3a (patch)
tree7c50ffb4c8f9ffbec236baf6f7a749c9e79e92e0
parentee79fef18748ad660d3a0471ed9a18ea11410849 (diff)
downloadpygobject-080e1a8e8c130a94b5662770621dea2ad1646b3a.tar.gz
Use optimized version of PyImport_ImportModule
https://gitlab.gnome.org/GNOME/pygobject/issues/123 You would expect PyImport_ImportModule to import a module once, store it's reference to sys.modules and the next time we call it with the same argument reuse the reference from sys.module. But it is not what is happening unfortunately. Everytime we call it it releases GIL, grabs global python import lock, grabs GIL back. The proposed optimization looks at sys.modules first and uses the reference from there to avoid GIL congestion. pyg_type_lookup is a good example of a function which imports python modules at run time and can cause GIL congestion.
-rw-r--r--gi/pygi-error.c2
-rw-r--r--gi/pygi-info.c2
-rw-r--r--gi/pygi-type.c2
-rw-r--r--gi/pyglib-python-compat.h17
4 files changed, 20 insertions, 3 deletions
diff --git a/gi/pygi-error.c b/gi/pygi-error.c
index 4827e9f4..26391411 100644
--- a/gi/pygi-error.c
+++ b/gi/pygi-error.c
@@ -376,7 +376,7 @@ pygerror_to_gvalue (GValue *value, PyObject *pyerror)
void
pygi_error_register_types (PyObject *module)
{
- PyObject *error_module = PyImport_ImportModule ("gi._error");
+ PyObject *error_module = PYGLIB_PyImport_ImportModule ("gi._error");
if (!error_module) {
return;
}
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 1b33e9a7..e46f6007 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -41,7 +41,7 @@ _generate_doc_string(PyGIBaseInfo *self)
static PyObject *_py_generate_doc_string = NULL;
if (_py_generate_doc_string == NULL) {
- PyObject *mod = PyImport_ImportModule ("gi.docstring");
+ PyObject *mod = PYGLIB_PyImport_ImportModule ("gi.docstring");
if (!mod)
return NULL;
diff --git a/gi/pygi-type.c b/gi/pygi-type.c
index 06d773a3..9561c432 100644
--- a/gi/pygi-type.c
+++ b/gi/pygi-type.c
@@ -35,7 +35,7 @@ _pygi_type_import_by_name (const char *namespace_,
module_name = g_strconcat ("gi.repository.", namespace_, NULL);
- py_module = PyImport_ImportModule (module_name);
+ py_module = PYGLIB_PyImport_ImportModule (module_name);
g_free (module_name);
diff --git a/gi/pyglib-python-compat.h b/gi/pyglib-python-compat.h
index d6f7553f..b1f4b222 100644
--- a/gi/pyglib-python-compat.h
+++ b/gi/pyglib-python-compat.h
@@ -115,6 +115,21 @@ PyTypeObject symbol = { \
return; \
PyDict_SetItemString(d, name, (PyObject *)&type);
+/* Better alternative to PyImport_ImportModule which tries to import from
+ * sys.modules first */
+static inline PyObject *
+PYGLIB_PyImport_ImportModule(const char *name)
+{
+ /* see PyImport_ImportModuleNoBlock
+ * https://github.com/python/cpython/blob/2.7/Python/import.c#L2166-L2206 */
+ PyObject *result = PyImport_ImportModuleNoBlock(name);
+ if (result)
+ return result;
+
+ PyErr_Clear();
+ return PyImport_ImportModule(name);
+}
+
#else
#define PYGLIB_MODULE_START(symbol, modname) \
@@ -157,6 +172,8 @@ PyTypeObject symbol = { \
return; \
PyDict_SetItemString(d, name, (PyObject *)&type);
+#define PYGLIB_PyImport_ImportModule PyImport_ImportModule
+
#define PYGLIB_PyBaseString_Check PyUnicode_Check
#define PYGLIB_PyUnicode_Check PyUnicode_Check