QML: Changes to multiple bindings from QAbstractModel derived class rendered differently on windows and macOS
-
Hey Community,
I have a really frustrating performance issue on windows when using QML with Qt 5.15
First lets have a video that shows my issue:
Mac: https://www.dropbox.com/s/p19ul7k39k8j4tw/macOS.mov?dl=0
Win: https://www.dropbox.com/s/yab5i1b8jy8m1ye/windows.mov?dl=0On Mac you see that changing the properties will have an instant update whereas on windows things load super slow in arbitrary order.
In QML I have a ListView where the data model is a list of QAbstractItemModels as well. The items (e.g. the “rating”) are within an asynchronous QML Loader.When updating the values of my model list I see a very different behaviour on macOS vs Windows.
On mac everything is updated in one batch, the log states that the rendering takes around 100ms
On windows, QML is rendering each change to the property individually… which is waaaay slower.This is the output using QSG_RENDER_TIMING=1
mac:… 27 05 2021 14:51:02.769 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 14:51:02.769 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 14:51:02.769 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 14:51:02.770 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 14:51:02.770 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 14:51:02.770 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 14:51:02.770 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 14:51:02.770 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 14:51:02.770 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 14:51:02.786 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=15ms, preprocess=0, updates=0, binding=0, rendering=15 27 05 2021 14:51:02.788 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderloop - Frame rendered with 'basic' renderloop in 101ms, polish=23, sync=32, render=44, swap=0, frameDelta=47917 27 05 2021 14:51:02.794 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=4ms, preprocess=0, updates=0, binding=0, rendering=4 27 05 2021 14:51:02.794 [0x00007f95e7f09f10] DEBUG Qt qt.scenegraph.time.renderloop - Frame rendered with 'basic' renderloop in 5ms, polish=0, sync=0, render=5, swap=0, frameDelta=6Windows:
… // skipped hundreds of lines 27 05 2021 17:34:09.650 [0x000001f57ad7e9f0] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=14ms, preprocess=1, updates=0, binding=0, rendering=12 27 05 2021 17:34:09.662 [0x000001f57ad7e9f0] DEBUG Qt qt.scenegraph.time.renderloop - Frame rendered with 'threaded' renderloop in 33ms, sync=1, render=21, swap=11 - (on render thread) 27 05 2021 17:34:09.664 [0x000001f5756bd020] DEBUG Qt qt.scenegraph.time.renderloop - Frame prepared with 'threaded' renderloop, polish=0, lock=0, blockedForSync=22, animations=0 - (on Gui thread) WinMain_QMLTYPE_981(0x1f57a536890 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window), title="Production", geometry=0,0 1919x977) 27 05 2021 17:34:09.666 [0x000001f57ad7e9f0] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 17:34:09.672 [0x000001f57ad7e9f0] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=6ms, preprocess=1, updates=0, binding=0, rendering=5 27 05 2021 17:34:09.682 [0x000001f57ad7e9f0] DEBUG Qt qt.scenegraph.time.renderloop - Frame rendered with 'threaded' renderloop in 19ms, sync=1, render=8, swap=9 - (on render thread) 27 05 2021 17:34:09.684 [0x000001f5756bd020] DEBUG Qt qt.scenegraph.time.renderloop - Frame prepared with 'threaded' renderloop, polish=0, lock=0, blockedForSync=13, animations=0 - (on Gui thread) WinMain_QMLTYPE_981(0x1f57a536890 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window), title="Production", geometry=0,0 1919x977) 27 05 2021 17:34:09.686 [0x000001f57ad7e9f0] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=0ms, preprocess=0, updates=0, binding=0, rendering=0 27 05 2021 17:34:09.697 [0x000001f57ad7e9f0] DEBUG Qt qt.scenegraph.time.renderer - time in renderer: total=11ms, preprocess=0, updates=0, binding=0, rendering=11 27 05 2021 17:34:09.711 [0x000001f57ad7e9f0] DEBUG Qt qt.scenegraph.time.renderloop - Frame rendered with 'threaded' renderloop in 28ms, sync=1, render=14, swap=13 - (on render thread) 27 05 2021 17:34:09.712 [0x000001f5756bd020] DEBUG Qt qt.scenegraph.time.renderloop - Frame prepared with 'threaded' renderloop, polish=0, lock=0, blockedForSync=23, animations=0 - (on Gui thread) WinMain_QMLTYPE_981(0x1f57a536890 active exposed, visibility=QWindow::Windowed, flags=QFlags<Qt::WindowType>(Window), title="Production", geometry=0,0 1919x977)I’ve tried to set the renderer to basic and to windows but it doesn’t change the behaviour at all.
In this particular case I really prefer the way Mac handles the redraw. I don’t care to see each individual change to my bound properties.
I wonder, is there a way to tell QML to first prepare everything and then to render all items in one go?My suspicion is that updating the properties on windows is magnitudes slower than on the Mac causing the render system to trigger a redraw way more frequent.
On Mac I used Xcode Instruments to see that pretty much all computing power is spent in an OpenGL related stack:31 QtQuick 106.0 QSGBatchRenderer::Renderer::renderBatches() /Users/qt/work/qt/qtdeclarative/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp:4051On windows I've used Very Sleepy but I am having a hard time to get my head around the findings. Most samples land in:
- QAbstractFileEngineHandler::~QAbstractFileEngineHandler 164.46s 69.87%
- QQuickPixmap::connectFinished 11.61s 4.93%
- QmlIR::IRBuilder::appendBinding 10.39s 4.41%
Thanks a ton for any help!