qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH for-1.5 1/2] qom: aggressively optimize qom casting


From: Anthony Liguori
Subject: [Qemu-devel] [PATCH for-1.5 1/2] qom: aggressively optimize qom casting
Date: Mon, 13 May 2013 15:31:45 -0500

This patch adds a small typename cache to ObjectClass.  This allows
caching positive casts within each ObjectClass.  Benchmarking a
PPC workload provided by Aurelien, this patch eliminates every
single g_hash_table_lookup() happening during the benchmark (which
was about 2 million per-second).

With this patch applied, I get exactly the same performance (within
the margin of error) as with --disable-qom-cast-debug.

N.B. it's safe to cache typenames only from the _assert() macros
because they are always called with string literals.

Signed-off-by: Anthony Liguori <address@hidden>
---
 include/qom/object.h |  4 ++++
 qom/object.c         | 40 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/include/qom/object.h b/include/qom/object.h
index 63e2a40..23fc048 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -344,6 +344,8 @@ typedef void (ObjectUnparent)(Object *obj);
  */
 typedef void (ObjectFree)(void *obj);
 
+#define OBJECT_CLASS_CAST_CACHE 4
+
 /**
  * ObjectClass:
  *
@@ -356,6 +358,8 @@ struct ObjectClass
     Type type;
     GSList *interfaces;
 
+    const char *cast_cache[OBJECT_CLASS_CAST_CACHE];
+
     ObjectUnparent *unparent;
 };
 
diff --git a/qom/object.c b/qom/object.c
index f5f416b..ec88231 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -439,7 +439,16 @@ Object *object_dynamic_cast_assert(Object *obj, const char 
*typename,
                                      typename, file, line, func);
 
 #ifdef CONFIG_QOM_CAST_DEBUG
-    Object *inst = object_dynamic_cast(obj, typename);
+    int i;
+    Object *inst;
+
+    for (i = 0; i < OBJECT_CLASS_CAST_CACHE; i++) {
+        if (obj->class->cast_cache[i] == typename) {
+            goto out;
+        }
+    }
+
+    inst = object_dynamic_cast(obj, typename);
 
     if (!inst && obj) {
         fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
@@ -448,6 +457,15 @@ Object *object_dynamic_cast_assert(Object *obj, const char 
*typename,
     }
 
     assert(obj == inst);
+
+    if (obj == inst) {
+        for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
+            obj->class->cast_cache[i - 1] = obj->class->cast_cache[i];
+        }
+        obj->class->cast_cache[i - 1] = typename;
+    }
+
+out:
 #endif
     return obj;
 }
@@ -510,7 +528,16 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass 
*class,
     trace_object_class_dynamic_cast_assert(class ? class->type->name : 
"(null)",
                                            typename, file, line, func);
 
-#ifndef CONFIG_QOM_CAST_DEBUG
+#ifdef CONFIG_QOM_CAST_DEBUG
+    int i;
+
+    for (i = 0; i < OBJECT_CLASS_CAST_CACHE; i++) {
+        if (class->cast_cache[i] == typename) {
+            ret = class;
+            goto out;
+        }
+    }
+#else
     if (!class->interfaces) {
         return class;
     }
@@ -523,6 +550,15 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass 
*class,
         abort();
     }
 
+#ifdef CONFIG_QOM_CAST_DEBUG
+    if (ret == class) {
+        for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
+            class->cast_cache[i - 1] = class->cast_cache[i];
+        }
+        class->cast_cache[i - 1] = typename;
+    }
+out:
+#endif
     return ret;
 }
 
-- 
1.8.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]