Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
5.14.2, 5.15.6
-
None
Description
I've been digging into why we have performance issues in our application and I have narrowed down a particularly bad bottleneck with a simple test example. I've attached the example to this ticket.
Admittedly this is a very complex hierarchy, and I am aware that likely one thing we need to do is reduce this complexity. However the esoteric example here does show what I seem to believe is an actual problem.
The example I provide is a simple window and then a deeply nested hierarchy where there's a grid view you can scroll around. The grid view has lots of elements in it. When you scroll around you'll notice that the scroll performance is awful. On my powerful macOS machine, I am getting serious dropped frames. Given this is a static hierarchy, I would imagine this should be something QML can cope with.
When I run through a sampling profiler (I used Instruments.app from Xcode) I find that the CPU is pegged and the hot path is this:
... snip ... QQuickWindow::wheelEvent(QWheelEvent*) QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent*) QQuickWindowPrivate::deliverSinglePointEventUntilAccepted(QQuickPointerEvent*) QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickWindowPrivate::pointerTargets(QQuickItem*, QQuickEventPoint*, bool, bool) const QQuickItem::mapFromScene(QPointF const&) con QQuickItemPrivate::windowToItemTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToWindowTransform() const QQuickItemPrivate::itemToParentTransform(QTransform&) const QList<QQuickTransform*>::isEmpty() const QListData::isEmpty() const
I took a look into the code here and it does seem relatively expensive doing all this. And for each child of the grid view, it'll be walking up the hierarchy and re-doing the same work over and over (if I understand correctly).
Since these XToYTransform functions are used a lot for hit testing, optimising all this could have significant impact to performance of complex hierarchies.
Is this something that Qt would be interested in improving?
Attachments
Issue Links
- depends on
-
QTBUG-109868 make QQuickDeliveryAgentPrivate::pointerTargets() iterative
-
- Reported
-
Gerrit Reviews
For Gerrit Dashboard: QTBUG-96304 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
452493,9 | Make QQuickDeliveryAgentPrivate::pointerTargets iterative | dev | qt/qtdeclarative | Status: NEW | -1 | 0 |