Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-96304

Performance bad in handling events (especially wheel events) in deep & large QML hierarchies

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Reported
    • Priority: P2: Important
    • Resolution: Unresolved
    • Affects Version/s: 5.14.2, 5.15.6
    • Fix Version/s: None
    • Labels:
      None
    • Platform/s:
      macOS, Windows

      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

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

            Assignee:
            srutledg Shawn Rutledge
            Reporter:
            mattjgalloway Matt Galloway
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Dates

              Created:
              Updated:

                Gerrit Reviews

                There are no open Gerrit changes