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

    • 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

        Issue Links

          For Gerrit Dashboard: QTBUG-96304
          # Subject Branch Project Status CR V

          Activity

            People

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

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There is 1 open Gerrit change