[Development] QTBUG-43096 - QML instantiation performance decadence

Robin Burchell robin.burchell at crimson.no
Fri May 25 22:35:58 CEST 2018

On Fri, May 25, 2018, at 9:14 PM, Uwe Rathmann wrote:
> On the Qt Conn 2016 Andrew ( Knight ) presented our very first results, 
> when comparing 4 different implementations of an average button.
> a) a button from Quick Controls 1
> b) a button from Quick Controls 2
> c) a custom button composed in QML ( this is your approach )
> d) a button from QSkinny
> All implementations have been done in QML with very similar code.
> Unfortunately the presentation has not been recorded, but out of my 
> memory one of our statistics was:
> a) > 30 QObjects
> b + c ) 7 QObjects
> d) 1 QObject

I'm familiar with numbers like that. I've come up with many similar ones myself in the past. The first point I would make in reply, though, is that the convenience of creating code with a/b/c are going to be significantly better in my experience.

And in addition, nothing (except the lack of a need to _actually_ go this far) stops me from writing a button using QSGNode instances today, without any use of private API and similarly avoiding many of those object allocations.

The one feature that would be a problem would be a missing public text node, which would mean I'd have to resort to a QQmlComponent with a Text item in it to set my label. Off the top of my head, that makes three QObjects, for the record: a QQuickItem for the button, a QObject (really a QQuickTextItem) from the component, and QQmlComponent itself, though that last one can be shared between buttons.

Adding a public text node would be nice if we wanted to make it a single QObject, but doesn't justify creating a whole new framework to me, given it's perfectly possible with the API of QtQuick today, and there is plenty of precedent (and demand) for it.

(And no, I don't think that just making QQuickTextNode public is the answer. That is a very, very heavy set of classes, it really needs some thought and cleanup applied first I think, alas, I don't know of anyone working on it today...)

> ( But we also noticed stuff like that: QQuickGradient is a QObject and 
> even QQuickGradientStop is one. So for the definition of a gradient with 
> 2 colors you need 3 QObjects: > 400 bytes. These little things could 
> easily being fixed by using Q_GADGET - but obviously nobody cares. )

It's not that nobody cares, it's that you can't actually do that without breaking code that probably[1] exists in the real world. Let's take another good example from the top of my head: Item::anchors. Behind the scenes, it's implemented as a QQuickAnchors, which is a QObject. Let's turn it into a Q_GADGET, and we're done, right?

Well, not quite, because now any code that does this:

    anchors { onLeftChanged { ... } }

or this:

    this.anchors.leftChanged.connect(function() { ... })

or in the C++ world:

    connect(myItem->anchors(), &QQuickAnchors::leftChanged, ...

... will break, since Q_GADGET doesn't have signals - so it's simply not equivilent.

It's nice to contemplate this sort of stuff, of course, and I'd love to see common features like anchors made cheaper (really, gradients aren't anywhere near as common, at least for the sake of my eyeballs I sure hope so), but doing so requires a careful approach, and probably a good chunk of grunt-work and magic that doesn't exist right now to make it actually happen, which is likely why it hasn't happened yet. Suggestions of how (or better still, patches), most certainly welcome.

[1]: almost certainly. my personal rule is: if there is API for it, someone will misuse it in the most awful way possible to make your life hell with it, somehow. I think one has to have a love-hate relationship with users, you can't live without them, but my god you wish you could sometimes ;-).

More information about the Development mailing list