Type checking
In a previous thread about sealing accessors and how that means more type checking, On Wed, 2010-03-17 at 17:10 +, Emmanuele Bassi wrote: > this might be the kick in the arse needed to get type checking down to a > minimal cost We have observed in the past that the type checking calls are 2-3% of program run time [that needs to be verified with the current stack, of course, but we've seen reports like that on the GTK lists within the last few years]. That's a lot :| I've often wondered about it, because on the one hand we have void gtk_button_set_label (GtkButton *button, const gchar *label) { g_return_if_fail (GTK_IS_BUTTON (button)); in gtk/gtkbutton.c which after wading through several macros ends up as a call to g_type_check_instance() in glib/gtype.c with some if/else blocks around it. Meanwhile most of the time (in C anyway) people call gtk_button_set_label(GTK_BUTTON(button), "Hello World"); which ends up as a call to g_type_check_instance_cast() which does most of the same stuff as g_type_check_instance() does. I'm aware of this partly because in java-gnome's generated code we ended up casting to the public types directly (wasn't my idea, it's what I inherited, and lo it works): GtkButton* button; ... button = (GtkButton*) user_data; gtk_button_set_label(button, "Hello World"); and it's been working for us because a) we have correct type information so we're casting the right thing anyway, and b) because the first thing the functions we are calling do is check the type of the inbound pointer. So I'm wondering: can we [C, GTK] do away with one of the code paths entirely? It'd be nice to do away with the checks in the internal accessors, of course, but that isn't going to happen because the internal code is now using the public accessors. So maybe we can at least not check in the cast macros? Again, I haven't profiled a C only applcation in a while, so this may be out of date. Someone with a GUI heavy C app would need to check. But this used to be really expensive for C apps. And meanwhile we're using GTK for some years now without using the cast macros at all, and things are working. So that's at least a datapoint. AfC Sydney -- Andrew Frederick Cowie Operational Dynamics is an operations and engineering consultancy focusing on IT strategy, organizational architecture, systems review, and effective procedures for change management: enabling successful deployment of mission critical information technology in enterprises, worldwide. http://www.operationaldynamics.com/ Sydney New York Toronto London signature.asc Description: This is a digitally signed message part ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Type checking
On 17/03/10 22:03, Andrew Cowie wrote: in gtk/gtkbutton.c which after wading through several macros ends up as a call to g_type_check_instance() in glib/gtype.c with some if/else blocks around it. [snip] So I'm wondering: can we [C, GTK] do away with one of the code paths entirely? It'd be nice to do away with the checks in the internal accessors, of course, but that isn't going to happen because the internal code is now using the public accessors. So maybe we can at least not check in the cast macros? Again, I haven't profiled a C only applcation in a while, so this may be out of date. Someone with a GUI heavy C app would need to check. But this used to be really expensive for C apps. And meanwhile we're using GTK for some years now without using the cast macros at all, and things are working. So that's at least a datapoint. Isn't this why we have G_DISABLE_CAST_CHECKS ? -- Regards, Martyn ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Type checking
On Thu, 2010-03-18 at 09:03 +1100, Andrew Cowie wrote: > I've often wondered about it, because on the one hand we have > > void > gtk_button_set_label (GtkButton *button, > const gchar *label) > { > g_return_if_fail (GTK_IS_BUTTON (button)); > > in gtk/gtkbutton.c which after wading through several macros ends up as > a call to g_type_check_instance() in glib/gtype.c with some if/else > blocks around it. the G_TYPE_CHECK_INSTANCE_TYPE() macro won't be disabled - ever. the only way to disable that particular type check is to compile with -DG_DISABLE_CHECKS, which disables g_return_*() -- and you don't really want to do that. > Meanwhile most of the time (in C anyway) people call > > gtk_button_set_label(GTK_BUTTON(button), "Hello World"); which can be disabled by using -DG_DISABLE_CAST_CHECKS, resulting in: #define GTK_BUTTON(obj) ((GtkButton *) (obj)) a plain, unchecked C cast. > and it's been working for us because a) we have correct type information > so we're casting the right thing anyway, and b) because the first thing > the functions we are calling do is check the type of the inbound > pointer. that's something only a binding could do - but only certain bindings can actually offer this degree of type checking. for most dynamic languages out there, the actual type check should be deferred to GObject. > So maybe we can at least not check in the cast macros? again, -DG_DISABLE_CAST_CHECKS does that. surrendering type checking in a run-time type system is giving up the little slice of safety it guarantees. we do type checking on both ends because we don't know what's been fed to the public API; private API should not have type checks (but they should assert() if the internal state is screwed). a stop gap solution is to avoid doing crazy stuff like: static void my_blah_widget_init (MyBlahWidget *widget) { gtk_widget_set_foo (GTK_WIDGET (widget), TRUE); gtk_widget_set_bar (GTK_WIDGET (widget), FALSE); gtk_widget_set_baz (GTK_WIDGET (widget), 42); } and do one since cast instead: static void my_blah_widget_init (MyBlahWidget *widget) { GtkWidget *w = GTK_WIDGET (widget); gtk_widget_set_foo (w, TRUE); gtk_widget_set_bar (w, FALSE); gtk_widget_set_baz (w, 42); } the real solution, though obviously more involved, is to make type checking faster; it's a common operation, so shaving 50% off would result in an overall benefit for everyone. the recent fixes Alexander wrote and that went into making type checks on interfaces an O(1) operation are a step in the right direction, especially for libraries that use interfaces a lot. ciao, Emmanuele. -- W: http://www.emmanuelebassi.name B: http://blogs.gnome.org/ebassi ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Type checking
Martyn Russell a écrit : > On 17/03/10 22:03, Andrew Cowie wrote: >> in gtk/gtkbutton.c which after wading through several macros ends up as >> a call to g_type_check_instance() in glib/gtype.c with some if/else >> blocks around it. > > [snip] > >> So I'm wondering: can we [C, GTK] do away with one of the code paths >> entirely? It'd be nice to do away with the checks in the internal >> accessors, of course, but that isn't going to happen because the >> internal code is now using the public accessors. >> >> So maybe we can at least not check in the cast macros? >> >> Again, I haven't profiled a C only applcation in a while, so this may be >> out of date. Someone with a GUI heavy C app would need to check. But >> this used to be really expensive for C apps. And meanwhile we're using >> GTK for some years now without using the cast macros at all, and things >> are working. So that's at least a datapoint. > > Isn't this why we have G_DISABLE_CAST_CHECKS ? > And G_DISABLE_CHECKS for g_return*s. If enabling them really worth it in terms of performances, builders (users, distributors, etc) may want to do so. But if G_DISABLE_CAST_CHECKS does only affect the program that is built with (it changes only the internal casts), G_DISABLE_CHECKS have more impact: the functions would no longer check their arguments, even when called from applications. So I think that using G_DISABLE_CAST_CHECKS may be a good idea if it have an impact on performances, but G_DISABLE_CHECKS is more questionable, and should probably not be the default. My 2 cents.. Colomban W. ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Type checking
2010/3/18 Emmanuele Bassi : > On Thu, 2010-03-18 at 09:03 +1100, Andrew Cowie wrote: > >> I've often wondered about it, because on the one hand we have >> >> void >> gtk_button_set_label (GtkButton *button, >> const gchar *label) >> { >> g_return_if_fail (GTK_IS_BUTTON (button)); >> >> in gtk/gtkbutton.c which after wading through several macros ends up as >> a call to g_type_check_instance() in glib/gtype.c with some if/else >> blocks around it. > > the G_TYPE_CHECK_INSTANCE_TYPE() macro won't be disabled - ever. the > only way to disable that particular type check is to compile with > -DG_DISABLE_CHECKS, which disables g_return_*() -- and you don't really > want to do that. That's actually "you can't really do that", disabling checks (or to be exact, using --disable-debug) would be nice enough for eg. embedded systems, but since applications (and libraries) tend to regularly feed invalid arguments to libraries and trust the library to handle it all you get from it is crashing applications. Even gio was broken wrt this: https://bugzilla.gnome.org/show_bug.cgi?id=593856 It's kind of a sad situation. :( -- Kalle Vahlman, z...@iki.fi Powered by http://movial.com Interesting stuff at http://sandbox.movial.com See also http://syslog.movial.fi ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Type checking
On Thu, 2010-03-18 at 07:30 +0200, Kalle Vahlman wrote: > > the G_TYPE_CHECK_INSTANCE_TYPE() macro won't be disabled - ever. the > > only way to disable that particular type check is to compile with > > -DG_DISABLE_CHECKS, which disables g_return_*() -- and you don't really > > want to do that. > > That's actually "you can't really do that", disabling checks (or to be > exact, using --disable-debug) would be nice enough for eg. embedded > systems, but since applications (and libraries) tend to regularly feed > invalid arguments to libraries and trust the library to handle it all > you get from it is crashing applications. Even gio was broken wrt > this: https://bugzilla.gnome.org/show_bug.cgi?id=593856 > > It's kind of a sad situation. :( that's different: --disable-debug (or --enable-debug=no) also adds -DG_DISABLE_ASSERT which you really, *really* don't want to do. using --enable-debug=minimum (which disables cast checks) and manually adding -DG_DISABLE_CHECKS to the CPPFLAGS should be enough for embedded environments. CAVEAT: I'm not advocating package maintainers on embedded systems to use --enable-debug=no *ever*, unless: • they audit all the code compiled beforehand • they come up with numbers that demonstrate the advantages of disabling the type checking layer against the potential failures in all other cases, running with --enable-debug=no is Just Plain Wrong™. been there, done that. ciao, Emmanuele. -- W: http://www.emmanuelebassi.name B: http://blogs.gnome.org/ebassi ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Type checking
On 03/17/2010 07:40 PM, Emmanuele Bassi wrote: > a stop gap solution is to avoid doing crazy stuff > like: > > static void > my_blah_widget_init (MyBlahWidget *widget) > { > gtk_widget_set_foo (GTK_WIDGET (widget), TRUE); > gtk_widget_set_bar (GTK_WIDGET (widget), FALSE); > gtk_widget_set_baz (GTK_WIDGET (widget), 42); > } > > and do one since cast instead: > > static void > my_blah_widget_init (MyBlahWidget *widget) > { > GtkWidget *w = GTK_WIDGET (widget); > > gtk_widget_set_foo (w, TRUE); > gtk_widget_set_bar (w, FALSE); > gtk_widget_set_baz (w, 42); > } https://bugzilla.gnome.org/show_bug.cgi?id=567256 has a very small patch that makes it so that: if (MY_IS_BLAH_WIDGET (widget)) { MyBlahWidget *mbw = MY_BLAH_WIDGET (widget); only does a single type check (if you compile with optimization, and my_blah_widget_get_type() is marked G_GNUC_CONST). I thought it would fix your case too, but it doesn't, because theoretically gtk_widget_set_foo() might cause @widget to stop being a widget, so it needs to typecheck it again... Pretty sure we could fix this too though, by changing _G_TYPE_CIT to use "g_type_is_a (_inst->g_class->g_type, __t)" instead of "g_type_check_instance_is_a (__inst, __t)". Except that instead of g_type_is_a(), it would have to be a new method that does exactly the same thing as g_type_is_a(), but is G_GNUC_PURE (and is therefore only safe to call in cases where you know the type's hierarchy isn't going to change in the future). (Marking _get_type() methods G_GNUC_CONST makes it tricky to forcibly initialize a type, but https://bugzilla.gnome.org/show_bug.cgi?id=605976 has a patch to add "g_type_ensure()" to hide the complexity.) Of course, this doesn't help Andrew's original case, where the is_a and the cast are in separate functions... -- Dan ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list