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
_______________________________________________
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development

Reply via email to