Re: g_type_instance_is_a() and gtk 2 speed



On Wed, 18 Jul 2001, Joel Becker wrote:

> Folks,
> 	A while back it was pointed out that there is a substantial
> timesink in G_TYPE_INSTANCE_IS_A(), due to the depth of inheritance
> tracing (see
> <Pine LNX 4 21 0106171307170 32484-100000 birgrave birnet private>).  As
> far as I can tell, nothing has been done in this area since.

unless interfaces are involved, inheritance checks are actually performed
in constant time, regardless of depth/types being checked (if interfaces
are involved, this becomes an O(log(n_interfaces_of_class)) operation).
so we are actually fairly quick for what we do, the substantial timesink
reported seems due to g_type_instance_is_a() being called very often.
the suggested improvement takes advantage of the fact that a very high
percentage of the reported checks seemed to be class_of_type_a == type_a
checks and optimizes that.
there was one open issue with the patch supplied, that of evaluating
macro arguments twice in the new check macros.

i suggested using static inline instead and got informed that that's a
gcc extension. i'm not quite sure that's true however, we're using quite
a couple of static inline functions in our header files (and export linkable
versions thereof for non inline capable compilers).
these are not gcc special cased but compilation thereof depends on whether
cc supports any of inline, __inline or __inline__. there are compilers out
there that do support inlining other than gcc, and those trigger our
static inline foo(); functions, i've yet to see a single bug report on
static inline failing on those systems however.

despite that, i did optimize the macros for gcc at least, i'll commit
the following patch in the next couple of days if i don't trigger any
problems with it. people are invited to test this out and report problems
back to me.


> 	Is there any consensus on what is to be done about this and
> other possible bottlenecks?  GTK+ 2 is flat out *SLOW* compared to 1.2.

g_type_instance_is_a() is most likely not the main cause for this, i haven't
done hard profiling so far, but intuitivity and a couple of alex' emails ;)
suggest that 2.0 signal emissions way outweight g_type_instance_is_a() in
bottlenecking.

Index: gobject/ChangeLog
===================================================================
RCS file: /cvs/gnome/glib/gobject/ChangeLog,v
retrieving revision 1.129
diff -u -u -r1.129 ChangeLog
--- gobject/ChangeLog	2001/07/10 22:37:08	1.129
+++ gobject/ChangeLog	2001/07/18 17:46:01
@@ -1,3 +1,9 @@
+Wed Jul 18 19:42:31 2001  Tim Janik  <timj gtk org>
+
+	* gtype.h: if __GNUC__ is defined, inline a test for an exact type
+	match for instances and classes in G_TYPE_CHECK_INSTANCE_TYPE() and
+	G_TYPE_CHECK_CLASS_TYPE() before calling g_type_instance_is_a().
+
 Tue Jul 10 18:50:16 2001  Tim Janik  <timj gtk org>
 
 	* gsignal.h (struct _GSignalQuery): fix misplaced comment.
Index: gobject/gtype.h
===================================================================
RCS file: /cvs/gnome/glib/gobject/gtype.h,v
retrieving revision 1.29
diff -u -u -r1.29 gtype.h
--- gobject/gtype.h	2001/07/02 05:02:13	1.29
+++ gobject/gtype.h	2001/07/18 17:46:02
@@ -367,12 +367,31 @@
 #  define _G_TYPE_CCC(cp, gt, ct)       ((ct*) cp)
 #endif /* G_DISABLE_CAST_CHECKS */
 #define _G_TYPE_CHI(ip)			(g_type_check_instance ((GTypeInstance*) ip))
-#define _G_TYPE_CIT(ip, gt)             (g_type_instance_is_a ((GTypeInstance*) ip, gt))
-#define _G_TYPE_CCT(cp, gt)             (g_type_class_is_a ((GTypeClass*) cp, gt))
 #define _G_TYPE_CVH(vl, gt)             (g_type_check_value_holds ((GValue*) vl, gt))
 #define _G_TYPE_CHV(vl)			(g_type_check_value ((GValue*) vl))
 #define _G_TYPE_IGC(ip, gt, ct)         ((ct*) (((GTypeInstance*) ip)->g_class))
 #define _G_TYPE_IGI(ip, gt, ct)         ((ct*) g_type_interface_peek (((GTypeInstance*) ip)->g_class, gt))
+#ifdef	__GNUC__
+#  define _G_TYPE_CIT(ip, gt)             ({ \
+  GTypeInstance *__inst = (GTypeInstance*) ip; GType __t = gt; gboolean __r; \
+  if (__inst && __inst->g_class && __inst->g_class->g_type == __t) \
+    __r = TRUE; \
+  else \
+    __r = g_type_instance_is_a (__inst, __t); \
+  __r; \
+})
+#  define _G_TYPE_CCT(cp, gt)             ({ \
+  GTypeClass *__class = (GTypeClass*) cp; GType __t = gt; gboolean __r; \
+  if (__class && __class->g_type == __t) \
+    __r = TRUE; \
+  else \
+    __r = g_type_class_is_a (__class, __t); \
+  __r; \
+})
+#else  /* !__GNUC__ */
+#  define _G_TYPE_CIT(ip, gt)             (g_type_instance_is_a ((GTypeInstance*) ip, gt))
+#  define _G_TYPE_CCT(cp, gt)             (g_type_class_is_a ((GTypeClass*) cp, gt))
+#endif /* !__GNUC__ */
 #define	G_TYPE_FLAG_RESERVED_ID_BIT	(1 << 30)
 extern GTypeDebugFlags			_g_type_debug_flags;
 

> This is not so much a big deal on fancy new machines, but on older stuff
> (which now is becoming the 'embedded' space) it is pretty noticeable.
> Esp on the smaller chips (rise/cyrix/etc) with little cache and little
> memory bandwidth.
> 	Just curious.
> 
> Joel
> 

---
ciaoTJ





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