[Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

Ulf Hermann ulf.hermann at qt.io
Mon Oct 23 15:34:48 CEST 2023


Hi Nikolai,

it would be interesting to see the QML code that produces this behavior. 
However, I can very well imagine what's happening there. This is likely 
the "value type reference" problem. The list is a "sequence type". It 
doesn't have an identity of its own but rather is only accessible as a 
copy from your property. However, in JavaScript there is no such thing 
as a value (or sequence) type. There are only objects and each object 
has a unique identity. Therefore, your list, upon access from 
JavaScript, is wrapped into a special JavaScript object so that you can 
interact with it. The special object gives you the illusion of a 
separate entity by refreshing its copy of the list whenever you read 
from it and by writing the copy back to the property whenever you change 
it. The illusion breaks down when you retrieve the list a second time, 
though. Lacking any actual identity information, the QML engine cannot 
find other instances of the same list when accessing it again. Therefore 
it has to create a new wrapper object every time.

In contrast to that, for QObject-derived types we have actual identity 
information. QObjectPrivate has a field for "declarative data" and there 
we store a pointer to the JavaScript wrapper.

There is no simple solution for this. We could probably add some 
book-keeping to our QObject wrapper in order to figure out which 
properties already have sequence (and value type) wrappers. This is more 
complicated than it sounds because value types can have properties of 
their own, value types can be stored in lists, and all of this recursively.

If you get qmlcachegen to compile the code to C++ with Qt6, you won't 
see the JavaScript wrappers for lists and value types anymore. The 
generated C++ code can store the values on the C++ stack instead. But 
there are restrictions: In the generated C++ code we can _not_ honor the 
object-like nature of value type and sequence references. Anything that 
would exploit it won't be compiled to C++. In particular, any function 
call and any writing to a property invalidates all value type and 
sequence instances currently on the stack. This is because their source 
properties may have been changed by code triggered from the function 
call or property write.

best regards,
Ulf


More information about the Interest mailing list