[pygobject] Optimize signal lookup in gi repository



commit c07404461b126206e369270b56e613f81369c70a
Author: Daniel Drake <dsd laptop org>
Date:   Mon Mar 18 16:08:09 2013 -0600

    Optimize signal lookup in gi repository
    
    Now that we have GSignalQuery results available to us when connecting
    signals, we already know which GType implements the signal in question.
    
    Therefore there is no need to traverse the class parent hierarchy
    looking for this, which takes a considerable amount of CPU time.
    
    There is also no need to canonicalize the signal name; both before
    and after this patch, by the time we reach this point we have already
    successfully looked up the signal name as presented from Python.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=696143

 gi/_gobject/pygobject.c  |  5 ++--
 gi/pygi-signal-closure.c | 59 +++++++++++++-----------------------------------
 gi/pygi-signal-closure.h |  1 +
 gi/pygi.h                |  4 +++-
 4 files changed, 23 insertions(+), 46 deletions(-)
---
diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c
index f300c1b..4ca360a 100644
--- a/gi/_gobject/pygobject.c
+++ b/gi/_gobject/pygobject.c
@@ -1657,8 +1657,9 @@ connect_helper(PyGObject *self, gchar *name, PyObject *callback, PyObject *extra
     if (!pyg_gtype_is_custom (query_info.itype)) {
         /* The signal is implemented by a non-Python class, probably
          * something in the gi repository. */
-        closure = pygi_signal_closure_new (self, name, callback, extra_args,
-                                          object);
+        closure = pygi_signal_closure_new (self, query_info.itype,
+                                           query_info.signal_name, callback,
+                                           extra_args, object);
     }
 
     if (!closure) {
diff --git a/gi/pygi-signal-closure.c b/gi/pygi-signal-closure.c
index 6e026de..20c6b56 100644
--- a/gi/pygi-signal-closure.c
+++ b/gi/pygi-signal-closure.c
@@ -20,47 +20,28 @@
 
 #include "pygi-private.h"
 
-/* Copied from glib */
-static void
-canonicalize_key (gchar *key)
-{
-    gchar *p;
-
-    for (p = key; *p != 0; p++)
-    {
-        gchar c = *p;
-
-        if (c != '-' &&
-            (c < '0' || c > '9') &&
-            (c < 'A' || c > 'Z') &&
-            (c < 'a' || c > 'z'))
-                *p = '-';
-    }
-}
-
 static GISignalInfo *
 _pygi_lookup_signal_from_g_type (GType g_type,
                                  const gchar *signal_name)
 {
     GIRepository *repository;
     GIBaseInfo *info;
-    GType parent;
+    GISignalInfo *signal_info = NULL;
 
     repository = g_irepository_get_default();
     info = g_irepository_find_by_gtype (repository, g_type);
-    if (info != NULL) {
-        GISignalInfo *signal_info;
-        signal_info = g_object_info_find_signal ((GIObjectInfo *) info, signal_name);
-        g_base_info_unref (info);
-        if (signal_info != NULL)
-            return signal_info;
-    }
-
-    parent = g_type_parent (g_type);
-    if (parent > 0)
-        return _pygi_lookup_signal_from_g_type (parent, signal_name);
-
-    return NULL;
+    if (info == NULL)
+        return NULL;
+
+    if (GI_IS_OBJECT_INFO (info))
+        signal_info = g_object_info_find_signal ((GIObjectInfo *) info,
+                                                 signal_name);
+    else if (GI_IS_INTERFACE_INFO (info))
+        signal_info = g_interface_info_find_signal ((GIInterfaceInfo *) info,
+                                                    signal_name);
+
+    g_base_info_unref (info);
+    return signal_info;
 }
 
 static void
@@ -192,26 +173,21 @@ pygi_signal_closure_marshal(GClosure *closure,
 
 GClosure *
 pygi_signal_closure_new_real (PyGObject *instance,
-                              const gchar *sig_name,
+                              GType g_type,
+                              const gchar *signal_name,
                               PyObject *callback,
                               PyObject *extra_args,
                               PyObject *swap_data)
 {
     GClosure *closure = NULL;
     PyGISignalClosure *pygi_closure = NULL;
-    GType g_type;
     GISignalInfo *signal_info = NULL;
-    char *signal_name = g_strdup (sig_name);
 
     g_return_val_if_fail(callback != NULL, NULL);
 
-    canonicalize_key(signal_name);
-
-    g_type = pyg_type_from_object ((PyObject *)instance);
     signal_info = _pygi_lookup_signal_from_g_type (g_type, signal_name);
-
     if (signal_info == NULL)
-        goto out;
+        return NULL;
 
     closure = g_closure_new_simple(sizeof(PyGISignalClosure), NULL);
     g_closure_add_invalidate_notifier(closure, NULL, pygi_signal_closure_invalidate);
@@ -238,8 +214,5 @@ pygi_signal_closure_new_real (PyGObject *instance,
         closure->derivative_flag = TRUE;
     }
 
-out:
-    g_free (signal_name);
-
     return closure;
 }
diff --git a/gi/pygi-signal-closure.h b/gi/pygi-signal-closure.h
index 4687f3f..ffdd29c 100644
--- a/gi/pygi-signal-closure.h
+++ b/gi/pygi-signal-closure.h
@@ -36,6 +36,7 @@ typedef struct _PyGISignalClosure
 } PyGISignalClosure;
 
 GClosure * pygi_signal_closure_new_real (PyGObject *instance,
+                                         GType g_type,
                                          const gchar *sig_name,
                                          PyObject *callback,
                                          PyObject *extra_args,
diff --git a/gi/pygi.h b/gi/pygi.h
index 88c1b90..f3f0c81 100644
--- a/gi/pygi.h
+++ b/gi/pygi.h
@@ -82,6 +82,7 @@ struct PyGI_API {
                                 GParamSpec *pspec,
                                 PyObject *value);
     GClosure * (*signal_closure_new) (PyGObject *instance,
+                                      GType g_type,
                                       const gchar *sig_name,
                                       PyObject *callback,
                                       PyObject *extra_args,
@@ -141,6 +142,7 @@ pygi_set_property_value (PyGObject *instance,
 
 static inline GClosure *
 pygi_signal_closure_new (PyGObject *instance,
+                         GType g_type,
                          const gchar *sig_name,
                          PyObject *callback,
                          PyObject *extra_args,
@@ -149,7 +151,7 @@ pygi_signal_closure_new (PyGObject *instance,
     if (_pygi_import() < 0) {
         return NULL;
     }
-    return PyGI_API->signal_closure_new(instance, sig_name, callback, extra_args, swap_data);
+    return PyGI_API->signal_closure_new(instance, g_type, sig_name, callback, extra_args, swap_data);
 }
 
 static inline PyObject *


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