Re: Some performance notes



On 6 Aug 2001, Owen Taylor wrote:

> > > > After I removed the g_object_class_install_property() stuff,
> > > > object creation was faster, but is still way to slow compared
> > > > to just malloc'ing plain C structs for holding the data.
> > 
> > assuming you don't use CONSTRUCT properties, i find this mildly
> > odd, can you provide two stand-alone test cases, one with the
> > g_object_class_install_property() stuff and one without?
> > 
> > > I can see places in the g_object_new()/g_type_create_instance()
> > > code paths which look like they could be optimized, but
> > > in the absence of real benchmarking information, that's
> > > fairly theoretical.
> > 
> > even if theoretical, i'd be interested in hearing what you'd want
> > to speed-up there, especially for g_type_create_instance().
> 
> * g_type_create_instance() Looks up the type node, involving a
>   separate lock/unlock 3 times. Two of these could be avoided with
>   private functions (at the expense of some code bloat)

we can't get rid of the write lock for prealloced types, and need
a read lock initially to get a hand at the type node to create an
instance for, but i guess we can get rid of the locks in the for()
loop which chains parent class intializers with storing type nodes
in supers[].

> * G_TYPE_IS_ABSTRACT() is fairly expensive, so the check
>   probably should be surrounded by #ifndef G_DISABLE_CHECKS

nope, instead G_TYPE_IS_ABSTRACT() should - at least internally -
be just a flag test, that's on of the TODO items at the top of
gtype.c:
 * - speedup checks for virtual types, steal a bit somewhere

> * If node->supers was stored as type nodes, not types, then
>   the walk over the supers to initialize could be done
>   without locking, since node->supers, and the relevant
>   parts of the type nodes are static once they are created.

good point. looking this over, storing type node pointers in
supers[] has the drawbacks:
- on sizeof(pointer)==8 systems, we increase memory usage by
  4*depth(foreach typenode) bytes
- all type nodes grow by an extra int to store the actual type id
- NODE_PARENT_TYPE() gains an extra indirection

however, as benefits, this will get rid of:
- a couple extra locks upon instance creation
- a few indirections upon is_a checks
- lookups such as lookup_type_node_L (prerequisite_node->supers[i])

also the NODE_PARENT_TYPE() drawback is prolly negligible as that
macro is used as lookup_type_node_L (NODE_PARENT_TYPE (node)) in
a couple places.

> That's what I see offhand in g_type_create_instance(). Without
> profiling data and some tests, I have no idea whether any of these
> area actually worthwhile changes.
> 
> (Object creation and destruction did not show up at all
> on my radar, but I wasn't profiling startup, just drawing.
> Even startup I think will be much more dominated by
> signal emission.) 

yup, i'd second that.

> > > A pretty noticeable improvement for the non-threaded case 
> > > would be to reduce locking overhead when we aren't 
> > > initialized for threads. 
> > > 
> > > #define G_READ_LOCK(rw_lock)    g_static_rw_lock_reader_lock (rw_lock)
> > > 
> > > in gobject.c is always a function call, but if you trace
> > > down the G_LOCK() macro used elsewhere, you'll see it doesn't
> > > make a function call unless threading is enabled.
> > 
> > do you have any indication of g_static_rw_lock_reader_lock() actually
> > consuming significant time for the non-threaded case?
> 
> Yes, in my profiling (debug off) it was eating about 4% of the
> CPU time. 

wow, that requires further investigation, as i vaguely remember a
profile of sebastian that indicated locks being pretty fast for
the non-threaded case.

> > > For the threaded case, some attention to locking and unlocking
> > > less would be good - for instance, look up a type node and
> > > keep the result, instead of keeping locking and looking it
> > > up. 
> > 
> > i'm not sure what you are imagining here, usually the type system
> > acquires and releases a read-lock per function call in order
> > to be able to lookup type nodes, unless callbacks are being called,
> > in which case locks have to be released.
> > obviously, type nodes can't be cached across different API entries
> > of the type system, so i'm not quite getting what you're aiming at.
> 
> In some cases, it may pay to add private entry points that take
> type nodes, rather than types.

take a look at the static functions, all of them that can, do indeed
already take a TypeNode* and not a GType already.

> 
> Regards,
>                                         Owen
> 

---
ciaoTJ





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