[pygobject: 2/3] gi/pygtype.c: avoid GIL congestion in pyg_type_lookup



commit aab23dbdb38c5c316c1939410e0301aa8b262143
Author: Mikhail Fludkov <fludkov me gmail com>
Date:   Wed Feb 7 16:03:42 2018 +0100

    gi/pygtype.c: avoid GIL congestion in pyg_type_lookup
    
    https://gitlab.gnome.org/GNOME/pygobject/issues/123
    
    GIL congestion can be caused when many threads emit signals with objects of
    boxed type up to Python. The code in pyg_type_lookup imports a python module
    corresponding to gtype, which is expensive and can cause GIL congestion. What
    the proposed patch of pyg_type_lookup does:
    
    - pygi_type_import_by_g_type is called only once per a gtype
    - early NULL return. For example GStreamer types benefit greatly from it.
      Because pyg_register_gtype_custom is not used and pyg_type_lookup always
      returns NULL for such types.

 gi/pygtype.c | 41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)
---
diff --git a/gi/pygtype.c b/gi/pygtype.c
index 85a6d829..760af56a 100644
--- a/gi/pygtype.c
+++ b/gi/pygtype.c
@@ -618,6 +618,14 @@ pyg_flags_get_value(GType flag_type, PyObject *obj, guint *val)
 }
 
 static GQuark pyg_type_marshal_key = 0;
+static GQuark pyg_type_marshal_helper_key = 0;
+
+typedef enum _marshal_helper_data_e marshal_helper_data_e;
+enum _marshal_helper_data_e {
+    MARSHAL_HELPER_NONE = 0,
+    MARSHAL_HELPER_RETURN_NULL,
+    MARSHAL_HELPER_IMPORT_DONE,
+};
 
 PyGTypeMarshal *
 pyg_type_lookup(GType type)
@@ -625,12 +633,33 @@ pyg_type_lookup(GType type)
     GType      ptype = type;
     PyGTypeMarshal     *tm = NULL;
 
-    /* recursively lookup types */
-    while (ptype) {
-        pygi_type_import_by_g_type (ptype);
+    if (type == G_TYPE_INVALID)
+       return NULL;
+
+    marshal_helper_data_e marshal_helper = GPOINTER_TO_INT (
+       g_type_get_qdata(type, pyg_type_marshal_helper_key));
+
+    /* If we called this function before with @type and nothing was found,
+     * return NULL early to not spend time in the loop below */
+    if (marshal_helper == MARSHAL_HELPER_RETURN_NULL)
+       return NULL;
+
+    /* Otherwise do recursive type lookup */
+    do {
+       if (marshal_helper == MARSHAL_HELPER_IMPORT_DONE)
+           pygi_type_import_by_g_type (ptype);
+
        if ((tm = g_type_get_qdata(ptype, pyg_type_marshal_key)) != NULL)
            break;
        ptype = g_type_parent(ptype);
+    } while (ptype);
+
+    if (marshal_helper == MARSHAL_HELPER_NONE) {
+       marshal_helper = (tm == NULL) ?
+           MARSHAL_HELPER_RETURN_NULL:
+           MARSHAL_HELPER_IMPORT_DONE;
+       g_type_set_qdata(type, pyg_type_marshal_helper_key,
+           GINT_TO_POINTER(marshal_helper));
     }
     return tm;
 }
@@ -653,8 +682,10 @@ pyg_register_gtype_custom(GType gtype,
 {
     PyGTypeMarshal *tm;
 
-    if (!pyg_type_marshal_key)
-        pyg_type_marshal_key = g_quark_from_static_string("PyGType::marshal");
+    if (!pyg_type_marshal_key) {
+       pyg_type_marshal_key = g_quark_from_static_string("PyGType::marshal");
+       pyg_type_marshal_helper_key = g_quark_from_static_string("PyGType::marshal-helper");
+    }
 
     tm = g_new(PyGTypeMarshal, 1);
     tm->fromvalue = from_func;


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