[pygobject] Fast path Python Property getter when accessed through GObject interfaces



commit 5b82051d23f8d759b6fa57a4e9327e300568c89f
Author: Simon Feltman <sfeltman src gnome org>
Date:   Sat Aug 9 02:30:43 2014 -0700

    Fast path Python Property getter when accessed through GObject interfaces
    
    Break do_get_property() call into a re-usable function.
    Call do_get_property() Python implementations instead of going through GObject
    machinery for Python GObjects. This gives a performance boost for Python
    GObject properties when accessed via. obj.get_property() and obj.props.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=723872

 gi/gobjectmodule.c |   11 ++++-------
 gi/pygi-property.c |   35 +++++++++++++++++++++++++++--------
 gi/pygi-property.h |    3 +++
 3 files changed, 34 insertions(+), 15 deletions(-)
---
diff --git a/gi/gobjectmodule.c b/gi/gobjectmodule.c
index 3248804..33da181 100644
--- a/gi/gobjectmodule.c
+++ b/gi/gobjectmodule.c
@@ -38,6 +38,7 @@
 
 #include "pygi-value.h"
 #include "pygi-error.h"
+#include "pygi-property.h"
 
 static GHashTable *log_handlers = NULL;
 static gboolean log_handlers_disabled = FALSE;
@@ -194,7 +195,6 @@ pyg_object_get_property (GObject *object, guint property_id,
                         GValue *value, GParamSpec *pspec)
 {
     PyObject *object_wrapper, *retval;
-    PyObject *py_pspec;
     PyGILState_STATE state;
 
     state = pyglib_gil_state_ensure();
@@ -206,14 +206,11 @@ pyg_object_get_property (GObject *object, guint property_id,
        return;
     }
 
-    py_pspec = pyg_param_spec_new(pspec);
-    retval = PyObject_CallMethod(object_wrapper, "do_get_property",
-                                "O", py_pspec);
-    if (retval == NULL || pyg_value_from_pyobject(value, retval) < 0) {
-       PyErr_Print();
+    retval = pygi_call_do_get_property (object_wrapper, pspec);
+    if (retval && pyg_value_from_pyobject (value, retval) < 0) {
+        PyErr_Print();
     }
     Py_DECREF(object_wrapper);
-    Py_DECREF(py_pspec);
     Py_XDECREF(retval);
 
     pyglib_gil_state_release(state);
diff --git a/gi/pygi-property.c b/gi/pygi-property.c
index 82811fb..cc4e839 100644
--- a/gi/pygi-property.c
+++ b/gi/pygi-property.c
@@ -23,6 +23,7 @@
 
 #include "pygi-private.h"
 #include "pygi-value.h"
+#include "pygparamspec.h"
 
 #include <girepository.h>
 
@@ -97,6 +98,26 @@ _pygi_lookup_property_from_g_type (GType g_type, const gchar *attr_name)
 }
 
 PyObject *
+pygi_call_do_get_property (PyObject *instance, GParamSpec *pspec)
+{
+    PyObject *py_pspec;
+    PyObject *retval;
+
+    py_pspec = pyg_param_spec_new (pspec);
+    retval = PyObject_CallMethod (instance, "do_get_property", "O", py_pspec);
+    if (retval == NULL) {
+        PyErr_Print();
+    }
+
+    Py_DECREF (py_pspec);
+    if (retval) {
+        return retval;
+    }
+
+    Py_RETURN_NONE;
+}
+
+PyObject *
 pygi_get_property_value (PyGObject *instance, GParamSpec *pspec)
 {
     GIPropertyInfo *property_info = NULL;
@@ -110,6 +131,12 @@ pygi_get_property_value (PyGObject *instance, GParamSpec *pspec)
         return NULL;
     }
 
+    /* Fast path which calls the Python getter implementation directly.
+     * See: https://bugzilla.gnome.org/show_bug.cgi?id=723872 */
+    if (pyg_gtype_is_custom (pspec->owner_type)) {
+        return pygi_call_do_get_property ((PyObject *)instance, pspec);
+    }
+
     Py_BEGIN_ALLOW_THREADS;
     g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
     g_object_get_property (instance->obj, pspec->name, &value);
@@ -123,14 +150,6 @@ pygi_get_property_value (PyGObject *instance, GParamSpec *pspec)
         goto out;
     }
 
-    /* Fast path which checks if this is a Python implemented Property.
-     * TODO: Make it even faster by calling the Python getter implementation
-     * directly. See: https://bugzilla.gnome.org/show_bug.cgi?id=723872 */
-    if (pyg_gtype_is_custom (pspec->owner_type)) {
-        py_value = pyg_param_gvalue_as_pyobject (&value, TRUE, pspec);
-        goto out;
-    }
-
     /* Attempt to marshal through GI.
      * The owner_type of the pspec gives us the exact type that introduced the
      * property, even if it is a parent class of the instance in question. */
diff --git a/gi/pygi-property.h b/gi/pygi-property.h
index a08fa40..064a062 100644
--- a/gi/pygi-property.h
+++ b/gi/pygi-property.h
@@ -36,6 +36,9 @@ pygi_get_property_value (PyGObject *instance,
 PyObject *
 pygi_get_property_value_by_name (PyGObject *self,
                                  gchar *param_name);
+PyObject *
+pygi_call_do_get_property       (PyObject *instance,
+                                 GParamSpec *pspec);
 
 gint
 pygi_set_property_value (PyGObject *instance,


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