Re: Some performance notes



On Mon, 6 Aug 2001, Johannes Stezenbach wrote:

> OK, I don't want to dig too deep into the internals of the
> GLib type system right now, but I did a few more tests
> (on a PIII/733 MHz):
> 
>   int i;
>   GObject *obj[10000];
>   for (i = 0; i < 10000; i++)
>     obj[i] = g_object_new (G_TYPE_OBJECT, NULL);
> 
> takes about 20 msecs. Not too bad ;-)
> 
> The same using
> 
>     obj[i] = g_cim_list_new ();
> 
> takes 700 msecs, having the following class hierarchy:
> 
>   GObject
>     GCimObject
>       GCimSerializable
>         GCimContainer
>           GCimList
> 
> GCimObject has two properties, GCimSerializable none, GCimContainer
> one and GCimList one (one string, one int and two enums).
> Commenting out all the g_object_class_install_property()
> calls and the corresponding arguments to g_object_new() in g_cim_list_new()
> makes the
> 
>     obj[i] = g_cim_list_new ();
> 
> run in 45 msecs.

try runing this test with putting
 (void) g_cim_list_new ();
before the loop, that way you don't count in the class initialization
which is about g_object_class_install_property(), signal creation etc.

> Superficially glancing over the code in gobject.c I can see
> two possible reasons for the g_object_new() slowness:
> - properties are identified by strings, where g_param_spec_pool_lookup()
>   has to parse the class_name:property_name combination (twice, once in
>   g_object_new_valist, and again in g_object_newv)

the "class_name:property_name" syntax is strongly deprecated, people
should just use "property_name". g_param_spec_pool_lookup() first
attempts to lookup the property as "property_name" and only if that fails
falls back to looking for ':'. so don't use "class_name:" prefixing and
you don't pay extra string-contents-shuffling performance penalty for
deprecated API ;)
a good point you make is g_object_new_valist() causing
g_param_spec_pool_lookup() to be evaluated twice for each property,
since it chains to g_object_newv(). it's probably a good idea to
seperate out the g_object_newv() core into an extra static function
to spare the extra lookups.

> - lots of copying of default values and init'ing with GParamSpecs,
>   GParameters and GValues while creating a GParameter array from the
>   va_list, splitting that into constructor args and normal args,
>   calling the object's constructor, setting non-constructor args
>   and emitting notify signals for them

don't let the code's complexity fool you, it's written to handle unlimted
numbers of construct and non-construct parameters, however the
normal case is none or 1 construct property per object, so that
code like:
      if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
        {
          GList *list = g_list_find (clist, pspec);
          if (!list)
            {
              g_warning (G_STRLOC ": construct property \"%s\" for object `%s' can't be set twice",
and:
  /* set remaining construction properties to default values */
  n_cvalues = n_total_cparams - n_cparams;
  cvalues = g_new (GValue, n_cvalues);
  while (clist)
    {
      GList *tmp = clist->next;
      GParamSpec *pspec = clist->data;
      GValue *value = cvalues + n_total_cparams - n_cparams - 1;
      value->g_type = 0;
      g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
      g_param_value_set_default (pspec, value);

usually boils down to a NOP.

> My (hopefully wrong) conclusion: The GLib property system may be fine
> for script language bindings or libglade kind of stuff, but if you
> want performance, don't use it.
> 
> I hope you vehemently disagree, and enlighten me why it is
> implemented the way it is.

i won't vehemently disagree with you, but disagree to some extend ;)
for one, strings aren't necessarily evil to handle performance-wise,
that's what we have GQuark for. for another, the whole of GObject/GType/
GSignal hasn't been optimized yet, i expect some significant improvements
in speed once a) i start tackling my optimization todos, b) we've
eliminated bottlenecks that hard profiling data exposes.

where (a) currently identifies major parformance impacts, i.e. from my
todo:

optimizations:
- make quarked datalist lookups a binary search instead of a linear one
- make g_param_spec_pool_lookup() operate on property_name quarks to
  spare string hashes
- use g_value_get_*() shortcuts in cclosure marshallers for immediate
  type matches
- eliminate closure usage for plain C signal handlers
- coalesce g_param_spec_pool_lookup()s in g_object_new_valist() and
  g_object_newv()

> 
> Regards,
> Johannes
> 

---
ciaoTJ





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