Constantly repainting a scene of 8000 invisible items, when a MouseArea also exists, causes high CPU usage


Constantly repainting a scene of 8000 invisible items, when a MouseArea also exists, causes high CPU usage



How to reproduce:



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.


QSGRootNode::~QSGRootNode()


QSGNodeUpdater::isNodeBlocked(QSGNode*, QSGNode*) const




2 Answers
2



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.



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.


opacity:0


visible: false


visible: false


false



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.


Animators


Animation



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.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages