diff options
author | Mikhail Fludkov <fludkov.me@gmail.com> | 2018-02-07 16:03:42 +0100 |
---|---|---|
committer | Mikhail Fludkov <misha@pexip.com> | 2018-02-07 18:18:53 +0100 |
commit | aab23dbdb38c5c316c1939410e0301aa8b262143 (patch) | |
tree | 757d477f64917e009d8c93d6ec65679d0341fc6c | |
parent | 080e1a8e8c130a94b5662770621dea2ad1646b3a (diff) | |
download | pygobject-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.c | 41 |
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; |