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

守給你的承諾、 提交于 2019-12-25 09:26:05

问题


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.


回答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.




回答2:


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.



来源:https://stackoverflow.com/questions/44330231/constantly-repainting-a-scene-of-8000-invisible-items-when-a-mousearea-also-exi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!