[pygobject: 1/3] Use optimized version of PyImport_ImportModule



commit 080e1a8e8c130a94b5662770621dea2ad1646b3a
Author: Mikhail Fludkov <fludkov me gmail com>
Date:   Wed Feb 7 16:36:26 2018 +0100

    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.

 gi/pygi-error.c           |  2 +-
 gi/pygi-info.c            |  2 +-
 gi/pygi-type.c            |  2 +-
 gi/pyglib-python-compat.h | 17 +++++++++++++++++
 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]