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

Ulf Hermann ulf.hermann at qt.io
Tue Oct 24 10:53:51 CEST 2023


> Actually, funnily enough, Qt.fontfamilies is an order of magnitude 
> faster than custom property wrapping the result of ::families. Dunno 
> why.  5s vs 500 ms for the sue case
> Still, checking on .lncludes(name) in javascript is seemingly also an 
> order of magnitude slower than sending family name to c++ and 
> prematurely exiting from there. 500 ms vs <50ms

In 5.15 Qt.fontFamilies() is a JavaScript method on the 'Qt' member of 
the JavaScript global object. It looks like this:

ReturnedValue QtObject::method_fontFamilies(const FunctionObject *b, 
const Value *, const Value *, int argc)
{
     QV4::Scope scope(b);
     if (argc != 0)
         THROW_GENERIC_ERROR("Qt.fontFamilies(): Invalid arguments");

     return 
scope.engine->fromVariant(QVariant(QQml_guiProvider()->fontFamilies()));
}

So, it wraps the QStringList into a QVariant and the QVaroamt into a JS 
object. I'm really surprised that the wrapping is faster than anything 
else, but I'm not surprised that access to its internals is slow.

In Qt6, this is a Q_INVOKABLE C++ method on the 'Qt' singleton. It 
returns the QStringList as-is and lets the QML engine do with it 
whatever it needs to do.

If this is a particularly hot code path, what you might try is create a 
QJSValue that holds a JS array of font families in C++ and then expose 
that instead of the QStringList. This way you tightly control the 
JavaScript wrapping of the list. In turn, you lose any type information. 
A QJSValue can be anything. However, in Qt5 you cannot use the type 
information anyway.

best,
Ulf


More information about the Interest mailing list