Re: gobject bench



On 27 Aug 2000, Havoc Pennington wrote:

> 
> Hi,
> 
> I wrote a little program and did some timings (celeron 400):
> 
> Creating lots of objects...
> Created 1000000 GObject instances in 0.86 seconds (8.6e-07 secs per object)
> Finalized 1000000 GObject instances in 1.01 seconds (1.01e-06 secs per object)
> Creating lots of zero-filled structs...
> Created 1000000 struct instances in 0.47 seconds (4.7e-07 secs per object)
> Finalized 1000000 struct instances in 0.59 seconds (5.9e-07 secs per object)
> 
> Oddly, per the comment in the source, using G_OBJECT(g_object_new())
> instead of (GObject*)g_type_create_instance() halves the speed of
> object creation. Removing the G_OBJECT() typecast from the unref()
> loop doesn't make any noticeable difference, so it must just be the
> set_valist() and other stuff in g_object_new(). Could likely optimize
> the common case where first_param_name == NULL by returning
> immediately.

ok, first, just for comparison, rerunning your bench program
on my machine, i.e.:
  model name      : Pentium III (Katmai)
  stepping        : 3
  cpu MHz         : 551.261
  cache size      : 512 KB
results in:

>Creating lots of objects...
>Created 1000000 GObject instances in 0.64 seconds (6.4e-07 secs per object)
>Finalized 1000000 GObject instances in 1.19 seconds (1.19e-06 secs per object)
>Creating lots of zero-filled structs...
>Created 1000000 struct instances in 0.35 seconds (3.5e-07 secs per object)
>Finalized 1000000 struct instances in 0.43 seconds (4.3e-07 secs per object)

then actually making use of your GBench implementation, by changing:
-      benches[i] = (GBench*)g_type_create_instance (G_TYPE_OBJECT);
+      benches[i] = (GBench*)g_type_create_instance (G_TYPE_BENCH);
produces:

>Creating lots of objects...
>Created 1000000 GObject instances in 0.78 seconds (7.8e-07 secs per object)
>Finalized 1000000 GObject instances in 1.92 seconds (1.92e-06 secs per object)
>Creating lots of zero-filled structs...
>Created 1000000 struct instances in 0.3 seconds (3e-07 secs per object)
>Finalized 1000000 struct instances in 0.4 seconds (4e-07 secs per object)

interestingly to note, just adding one more cast:
-      benches[i] = (GBench*)g_type_create_instance (G_TYPE_OBJECT);
+      benches[i] = G_BENCH(g_type_create_instance (G_TYPE_BENCH));
results in:

>Creating lots of objects...
>Created 1000000 GObject instances in 1.06 seconds (1.06e-06 secs per object)
>Finalized 1000000 GObject instances in 1.91 seconds (1.91e-06 secs per object)
>Creating lots of zero-filled structs...
>Created 1000000 struct instances in 0.3 seconds (3e-07 secs per object)
>Finalized 1000000 struct instances in 0.43 seconds (4.3e-07 secs per object)

so there's quite some overhead introduced by casting to a derived type.
thusly adding #define G_DISABLE_CAST_CHECKS prior to glib-object.h
inclusion goes back to 0.78 seconds for object creation, and because of
  static void
  g_bench_finalize (GObject *object)
  {
    GBench *bench;

    bench = G_BENCH (object);

    G_OBJECT_CLASS (parent_class)->finalize (object);
  }
it also cuts on finalization time:

>Creating lots of objects...
>Created 1000000 GObject instances in 0.74 seconds (7.4e-07 secs per object)
>Finalized 1000000 GObject instances in 1.06 seconds (1.06e-06 secs per object)
>Creating lots of zero-filled structs...
>Created 1000000 struct instances in 0.3 seconds (3e-07 secs per object)
>Finalized 1000000 struct instances in 0.4 seconds (4e-07 secs per object)


from there, switching to g_object_new():
-      benches[i] = G_BENCH(g_type_create_instance (G_TYPE_BENCH));
+      benches[i] = G_BENCH(g_object_new (G_TYPE_BENCH,NULL));
yields:

>Creating lots of objects...
>Created 1000000 GObject instances in 0.87 seconds (8.7e-07 secs per object)
>Finalized 1000000 GObject instances in 1.1 seconds (1.1e-06 secs per object)
>Creating lots of zero-filled structs...
>Created 1000000 struct instances in 0.32 seconds (3.2e-07 secs per object)
>Finalized 1000000 struct instances in 0.38 seconds (3.8e-07 secs per object)

that's not much overhead for 1000000 object creations at all.
considering that g_object_new() internally does call g_object_new_valist(),
which then _does_ check first_param_name != NULL before calling
g_object_set_valist(), the additional overhead is prolly just caused by 
the two extra function calls and twice doing:
  g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);

btw, judging from the jitter in the above numbers and from what i encountered
upon multiple invokations of the same compiled version, the sampling error is
probably somewhere around 0.05 seconds, so take these numbers with an
apropriate amount of salt ;)


> So anyway, this seems to demonstrate that the time overhead of GObject
> creation is pretty low, about a constant factor of 2 more than a plain
> calloc() struct, including custom init/finalize methods. This suggests

you didn't create GBranch but GObject in your testfile, so you weren't
using the customized initializers/finalizers. (that's why i pasted
multiple test cases above)

> that speed should not be a concern when deciding whether to make a
> type a GObject or a plain struct; probably the size of the struct is
> the only real issue, if you have a huge number of instances and only a
> couple fields then GObject could cause some bloat. Also of course
> GObject prevents static allocation, which can matter for something
> like PangoFontDescription.
> 
> I can check in the bench program if you want, I don't guess it's that
> exciting though.

i might extend it to do some signal emission tests, so don't be
amazed if gbench.c finally ends up somewhere in CVS ;)

> 
> Havoc
> 

---
ciaoTJ







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