[Development] Reducing number of allocations in metacall argument marshalling

Kuba Ober kuba at mareimbrium.org
Wed Jan 15 19:42:01 CET 2014


Currently, the metacall arguments are marshaled by copy-constructing them in their own
heap blocks. The addresses to the copies are deposited in an array-of-void*, passed
as the args argument to QObject::qt_metacall etc.

So there are two layers of allocations:

1. An array of void* is heap-allocated.
2. It’s filled with pointers to heap-allocated copies of each argument.
 
The void** args protocol can be preserved, but instead of allocating copies on the heap, they
could be in-place-constructed right after the pointers. So args would be an array that has:

pointer-to-return-value-instance
pointer-to-arg1-instance
…
pointer-to-argn-instance
nullptr
return-value-instance
arg1-instance
…
argn-instance

If any of the pointers is zero, the instance would not be present in the array (it will not
occupy an instance space).

The metatype system stores the size of types known to it, so it’s a simple matter to
know how big the all-in-one array needs to be, taking alignment into consideration, of course.

I don’t know yet if such a change would be binary compatible, that needs further checking
of course. Initially it looks as if it would be compatible, since the QMetaCallEvent class
is internal only, just as queued_activate is etc.

I would like to know if such a change would be considered useful. The potential for
underlying allocator global lock contention is much smaller, besides not paying
the uncontested lock allocation costs, and simply using a bit less memory for every
metacall event.

As an extension of this approach, one could provide a factory method in `QMetaCallEvent`
that would allocate the proper amount of memory all in one go (to fit the event, the
arguments, and possibly the types when it owns the types).

Does this make sense?

Cheers, Kuba Ober


More information about the Development mailing list