summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Fludkov <fludkov.me@gmail.com>2018-02-07 16:03:42 +0100
committerMikhail Fludkov <misha@pexip.com>2018-02-07 18:18:53 +0100
commitaab23dbdb38c5c316c1939410e0301aa8b262143 (patch)
tree757d477f64917e009d8c93d6ec65679d0341fc6c
parent080e1a8e8c130a94b5662770621dea2ad1646b3a (diff)
downloadpygobject-aab23dbdb38c5c316c1939410e0301aa8b262143.tar.gz
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.
-rw-r--r--gi/pygtype.c41
1 files 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;