gstvalue: Speed up gst_value_intersect/_subtract
authorEdward Hervey <edward@collabora.com>
Tue, 17 Jun 2014 05:31:48 +0000 (07:31 +0200)
committerEdward Hervey <bilboed@bilboed.com>
Tue, 17 Jun 2014 14:27:07 +0000 (16:27 +0200)
Both gst_value_intersect and gst_value_subtract will call
gst_value_compare if one of their arguments isn't a list.

gst_value_compare will then re-do a check to see if one of
the arguments is a list (for the special case of comparing a unitary
value with a list of length 1).

The problem is that the various G_VALUE_HOLDS represent an expensive
amount of calling gst_value_compare (almost half of it) to see if
the provided arguments are list. These checks can be done without
when we know that the arguments aren't lists.

* Create a new "nolist" gst_value_compare which avoids that special
  case comparision

Benchmarks:
 valgrind/callgrind: average speedup in instruction calls for
 gst_value_intersect and gst_value_subtract is around 56% (Makes 63%
 of the calls it used to take previously)

 tests/benchmarks/capsnego: With default settings (depth 4, children 3
 607 elements), time taken for transition from READY to PAUSED:
   Before : 00.391519153
   After  : 00.220397492
    56% of the time previously used, +77% speedup

https://bugzilla.gnome.org/show_bug.cgi?id=731756

gst/gstvalue.c

index e4932bc..a03c5ab 100644 (file)
@@ -4460,6 +4460,27 @@ gst_value_list_equals_range (const GValue * list, const GValue * value)
   return FALSE;
 }
 
+/* "Pure" variant of gst_value_compare which is guaranteed to
+ * not have list arguments and therefore does basic comparisions
+ */
+static inline gint
+_gst_value_compare_nolist (const GValue * value1, const GValue * value2)
+{
+  GstValueCompareFunc compare;
+
+  if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
+    return GST_VALUE_UNORDERED;
+
+  compare = gst_value_get_compare_func (value1);
+  if (compare) {
+    return compare (value1, value2);
+  }
+
+  g_critical ("unable to compare values of type %s\n",
+      g_type_name (G_VALUE_TYPE (value1)));
+  return GST_VALUE_UNORDERED;
+}
+
 /**
  * gst_value_compare:
  * @value1: a value to compare
@@ -4476,7 +4497,6 @@ gst_value_list_equals_range (const GValue * list, const GValue * value)
 gint
 gst_value_compare (const GValue * value1, const GValue * value2)
 {
-  GstValueCompareFunc compare;
   GType ltype;
 
   g_return_val_if_fail (G_IS_VALUE (value1), GST_VALUE_LESS_THAN);
@@ -4533,17 +4553,8 @@ gst_value_compare (const GValue * value1, const GValue * value2)
     return GST_VALUE_EQUAL;
   }
 
-  if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
-    return GST_VALUE_UNORDERED;
-
-  compare = gst_value_get_compare_func (value1);
-  if (compare) {
-    return compare (value1, value2);
-  }
-
-  g_critical ("unable to compare values of type %s\n",
-      g_type_name (G_VALUE_TYPE (value1)));
-  return GST_VALUE_UNORDERED;
+  /* And now handle the generic case */
+  return _gst_value_compare_nolist (value1, value2);
 }
 
 /*
@@ -4760,7 +4771,7 @@ gst_value_intersect (GValue * dest, const GValue * value1,
   if (G_VALUE_HOLDS (value2, ltype))
     return gst_value_intersect_list (dest, value2, value1);
 
-  if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
+  if (_gst_value_compare_nolist (value1, value2) == GST_VALUE_EQUAL) {
     if (dest)
       gst_value_init_and_copy (dest, value1);
     return TRUE;
@@ -4857,7 +4868,7 @@ gst_value_subtract (GValue * dest, const GValue * minuend,
     }
   }
 
-  if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) {
+  if (_gst_value_compare_nolist (minuend, subtrahend) != GST_VALUE_EQUAL) {
     if (dest)
       gst_value_init_and_copy (dest, minuend);
     return TRUE;