1

How to reproduce:

  • Run my code
  • Keep the mouse over the window that appears

You'll see that CPU usage is fairly high, although it will depend on your hardware. On my PC it's 20% (5% in each of the 4 virtual cores).

My motivation for this testcase: in my real app I have a lot of invisible (culled) items, and while that the culling helps a lot with the CPU usage, it doesn't help as much as I'd expect.

I'd like ideas on why the CPU usage is so high, and how to reduce it.

My code:

main.qml:

import QtQuick 2.5
import QtQuick.Window 2.2

Window {
    visible: true
    width: 800
    height: 500

    MouseArea {
        width: 1
        height: 1
        hoverEnabled: true
    }
    AnimatedItem {
        anchors.centerIn: parent
        width: 100
        height: 100
    }

    Repeater {
        model: 8000
        Item {
            opacity: 0
            layer.enabled: true
            width: 1
            height: 1
        }
    }
}

AnimatedItem.qml:

import QtQuick 2.0

Rectangle {
    id: root
    color: "black"
    property real rotAngle: 0
    NumberAnimation on rotAngle {
        from: 0
        to: 360
        loops: Animation.Infinite
        running: true
        duration: 500
    }
    transform: Rotation {
        origin.x: root.width / 2
        origin.y: root.height / 2
        angle: root.rotAngle
    }
}

I've profiled it with the QML profiler, which has shown that insignificant time is spent in QML. So I've also profiled with a C++ profiler (CodeXL). It reports that the majority of time is spent in QSGRootNode::~QSGRootNode(), due to it calling QSGNodeUpdater::isNodeBlocked(QSGNode*, QSGNode*) const. I've looked at the Qt source but haven't been able to figure out why it's even calling the former.

Stefan Monov
  • 11,332
  • 10
  • 63
  • 120

2 Answers2

1

I found a solution that works at least in the testcase:

Set the parent of culled items to null, then set it back when they're unculled.

In some runs it doesn't help in my real app, but I'm not going to go deeper into this.

Stefan Monov
  • 11,332
  • 10
  • 63
  • 120
1

Save the GPU with visibility:false

Seems you are confused about the visibility thing, opacity:0 is not the same as visible: false. Just set visible: false and items won't be rendered, but by leaving opacity at zero, the item not only still renders, but causes blending operations. Make visibility false and you'll save GPU memory and cycles.

Save the CPU stopping animations

On the other hand, if items are not visible, a good idea is to stop animations, then you save CPU cycles too.

Save CPU and be smooth with Animators

On the other hand, if you must animate them, then prefer to use Animators and not Animations. Animations inform about every change, and Animators do not, so if you do not need to track status, then you save some CPU by using Animators. There is even a specific RotationAnimator.

Go deep and create your own item

Finally, if you have lots of identical items and you must animate them and you are really an optimization junkie (or you are running on embedded) then you should implement a custom QQuickItem and do the animation in a geometry shader.

There are some other more exotic ideas, but you could improve a lot with the above list.

Ariel M.
  • 896
  • 8
  • 24