Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
5.15.9, 5.15.15, 6.5.2
-
Device: i.MX6 Dual
OS: Yocto dunfell based distribution (GCC 9.3.0)
Kernel: 6.1.21
Description
Our UI application currently targeting with Qt 5.15.x is experiencing periodical stutters of ~900ms every few minutes. From the garbage collection debug logging we can see that this stutter is due to the garbage collection.
Example of GC logging:
Aug 02 13:04:59 ========== GC ==========|:0|GUI Aug 02 13:04:59 Allocated 82446336 bytes in 1276 chunks|:0|GUI Aug 02 13:04:59 Fragmented memory before GC 111168|:0|GUI Aug 02 13:04:59 Slot map for Block allocator:|:0|GUI Aug 02 13:04:59 number of entries in slot 0 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 1 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 2 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 3 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 4 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 5 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 6 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 7 : 0|:0|GUI Aug 02 13:04:59 total mem in bins 0|:0|GUI Aug 02 13:04:59 Slot map for InternalClass allocator:|:0|GUI Aug 02 13:04:59 number of entries in slot 0 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 1 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 2 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 3 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 4 : 75|:0|GUI Aug 02 13:04:59 number of entries in slot 5 : 0|:0|GUI Aug 02 13:04:59 number of entries in slot 6 : 51|:0|GUI Aug 02 13:04:59 number of entries in slot 7 : 33|:0|GUI Aug 02 13:04:59 total mem in bins 76928|:0|GUI Aug 02 13:05:00 triggered by unmanaged heap:|:0|GUI Aug 02 13:05:00 old unmanaged heap size: 4194349|:0|GUI Aug 02 13:05:00 new unmanaged heap: 2044979|:0|GUI Aug 02 13:05:00 unmanaged heap limit: 4194304|:0|GUI Aug 02 13:05:00 Slot map for Block allocator:|:0|GUI Aug 02 13:05:00 number of entries in slot 0 : 0|:0|GUI Aug 02 13:05:00 number of entries in slot 1 : 8887|:0|GUI Aug 02 13:05:00 number of entries in slot 2 : 7378|:0|GUI Aug 02 13:05:00 number of entries in slot 3 : 3056|:0|GUI Aug 02 13:05:00 number of entries in slot 4 : 1742|:0|GUI Aug 02 13:05:00 number of entries in slot 5 : 3253|:0|GUI Aug 02 13:05:00 number of entries in slot 6 : 2353|:0|GUI Aug 02 13:05:00 number of entries in slot 7 : 11122|:0|GUI Aug 02 13:05:00 total mem in bins 13561632|:0|GUI Aug 02 13:05:00 Slot map for InternalClasss allocator:|:0|GUI Aug 02 13:05:00 number of entries in slot 0 : 0|:0|GUI Aug 02 13:05:00 number of entries in slot 1 : 0|:0|GUI Aug 02 13:05:00 number of entries in slot 2 : 60|:0|GUI Aug 02 13:05:00 number of entries in slot 3 : 0|:0|GUI Aug 02 13:05:00 number of entries in slot 4 : 76|:0|GUI Aug 02 13:05:00 number of entries in slot 5 : 0|:0|GUI Aug 02 13:05:00 number of entries in slot 6 : 52|:0|GUI Aug 02 13:05:00 number of entries in slot 7 : 37|:0|GUI Aug 02 13:05:00 total mem in bins 82432|:0|GUI Aug 02 13:05:00 Marked object in 732049 us.|:0|GUI Aug 02 13:05:00 1312570 objects marked|:0|GUI Aug 02 13:05:00 Sweeped object in 216253 us.|:0|GUI Aug 02 13:05:00 Used memory before GC: 82335168|:0|GUI Aug 02 13:05:00 Used memory after GC: 62544608|:0|GUI Aug 02 13:05:00 Freed up bytes : 19790560|:0|GUI Aug 02 13:05:00 Freed up chunks : 97|:0|GUI Aug 02 13:05:00 ======== End GC ========|:0|GUI
Simple example application with which I can see similar behavior:
import QtQuick 2.15 import QtQuick.Window 2.15 Window { id: window width: 640 height: 480 visible: true title: qsTr("Rectangles") readonly property int staticRectCount: 100000 readonly property int dynamicRectCount: 100 // Static, invisible objects consuming memory from the JS heap. Repeater { model: staticRectCount Rectangle { visible: false x: Math.random() * window.width y: Math.random() * window.height width: Math.random() * 20 height: Math.random() * 20 color: Qt.rgba(Math.random(),Math.random(),Math.random(), 1) } } // Dynamic, visible objects with properties changing on interval, presumably // causing dynamic memory allocations and frees. Repeater { id: changingRects model: dynamicRectCount Rectangle { visible: true x: Math.random() * window.width y: Math.random() * window.height width: Math.random() * 20 height: Math.random() * 20 color: Qt.rgba(Math.random(),Math.random(),Math.random(), 1) } } Timer { interval: 2000; running: true; repeat: true onTriggered: changingRects.model = dynamicRectCount + Math.random() * 20 } // Rectangle moving smoothly accross the screen. // Updates to this should stay smooth over any garbage collection. // // Note: not using animation, as I've understood that those could happen in // separate render thread instead of the main thread Rectangle { id: movingRect visible: true x: 0 y: 0 width: 100 height: 100 color: "red" } Timer { interval: 40; running: true; repeat: true onTriggered: { movingRect.x++; if (movingRect.x > window.width) { movingRect.x = 0; } } } }
Not sure how representative the above is to what our application is actualy doing.
However, in a quick test the above would result in the GC running every 21 minutes and taking ~900ms:
qt.qml.gc.allocatorStats: Marked object in 516237 us. qt.qml.gc.allocatorStats: 302094 objects marked qt.qml.gc.allocatorStats: Sweeped object in 424215 us. qt.qml.gc.allocatorStats: Used memory before GC: 32198560 qt.qml.gc.allocatorStats: Used memory after GC: 16114400 qt.qml.gc.allocatorStats: Freed up bytes : 16084160 qt.qml.gc.allocatorStats: Freed up chunks : 216
Attached a full project, which I used in my test.
Attachments
Issue Links
- resulted in
-
QTBUG-119274 Introduce an incremental garbage collector for QML
- Open
- mentioned in
-
Page Loading...