QML memory increase continuously
-
Hi, all.
I am dealing with QML memory increasement all this week. It can be easily reproduced with simple code below.(Qt 5.12.9, embedded linux system)informations:
-
I use “cat /proc/.../status | grep "VmSize|VmRSS" to observe memory increase, it grows fast. Also I realize that Linux allocates memory more than app needs, so I use another app to allocate all left memory to make the data more trusting. Sadly, it still grows.
-
gc() function is called, but only a few memory is freed.
-
Valgrind is also used, the result is below. The definitely and indirectly lost does not match the real consumption. I doubt the "still reachable memory" is the main reason.
-
In souce code, I found the QQmlContextData seems not released. It is maintained by the parent context. (QQmlObjectCreator::create)
context = new QQmlContextData; context->isInternal = true; context->imports = compilationUnit->typeNameCache; context->initFromTypeCompilationUnit(compilationUnit, subComponentIndex); context->setParent(parentContext);
My question:
-
When will QQmlContextData release? Why its life circle is not same with the QObject created(the component)? (when destroy() is called, it only call deleteLater(), then delete self pointer. the QObjects only contains self with QQmlData(in declativeData))
-
Do you have suggestions about the memory control? The memory increasement is obviously not acceptable on embedded system.
-
Why QML uses so large memories? I guess the memory is in two parts: C++/Js Engine. the gc() function only release a little, not all, even destroy() called.
Valgrind test:
==31907== 120 bytes in 15 blocks are definitely lost in loss record 1,308 of 1,988 ==31907== at 0x4841D20: operator new[](unsigned long) (vg_replace_malloc.c:433) ==31907== by 0x590C647: QStringHash<QPair<int, QQmlPropertyData*> >::linkAndReserve(QStringHash<QPair<int, QQmlPropertyData*> > const&, int) (in /usr/lib/libQt5Qml.so.5.12.9) ==31907== 1,701 (512 direct, 1,189 indirect) bytes in 1 blocks are definitely lost in loss record 1,847 of 1,988 ==31907== at 0x48434E8: realloc (vg_replace_malloc.c:836) ==31907== by 0x71344E7: FcPatternObjectInsertElt (in /usr/lib/libfontconfig.so.1.9.2) ==31907== 8,152 bytes in 1,019 blocks are definitely lost in loss record 1,921 of 1,988 ==31907== at 0x4841D20: operator new[](unsigned long) (vg_replace_malloc.c:433) ==31907== by 0x58E29BF: QQmlContextData::initFromTypeCompilationUnit(QQmlRefPointer<QV4::CompiledData::CompilationUnit> const&, int) (in /usr/lib/libQt5Qml.so.5.12.9) ==31907== 189,152 bytes in 1,028 blocks are still reachable in loss record 1,987 of 1,988 ==31907== at 0x484166C: operator new(unsigned long) (vg_replace_malloc.c:344) ==31907== by 0x592E87F: QQmlObjectCreator::create(int, QObject*, QQmlInstantiationInterrupt*) (in /usr/lib/libQt5Qml.so.5.12.9) ==31907== ==31907== 469,602 bytes in 175 blocks are still reachable in loss record 1,988 of 1,988 ==31907== at 0x4841054: malloc (vg_replace_malloc.c:309) ==31907== by 0x7175EF3: ft_mem_qalloc (in /usr/lib/libfreetype.so.6.11.4) ==31907== ==31907== LEAK SUMMARY: ==31907== definitely lost: 8,784 bytes in 1,035 blocks ==31907== indirectly lost: 1,189 bytes in 43 blocks ==31907== possibly lost: 2,840 bytes in 18 blocks ==31907== still reachable: 3,185,715 bytes in 19,864 blocks ==31907== of which reachable via heuristic: ==31907== newarray : 74,704 bytes in 44 blocks ==31907== multipleinheritance: 136 bytes in 2 blocks ==31907== suppressed: 0 bytes in 0 blocks
Souce code:
import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import "qrc:/res/qml" import QtQuick.Window 2.2 ApplicationWindow { id: window width: 960 height: 480 title: "Buttons" visible: true ScrollView { width: 960 height : 240 y: 120 Column { id: contentView width: parent.width leftPadding: 10 spacing: 5 property var objArr : [] Button { id: btnCreate width: 300 height : 50 text : qsTr("create items") onClicked: { for(var i =0 ; i < 20000; i++) { var obj = itemView.createObject(container); contentView.objArr.push(obj); } console.log("create " + i + " views"); } } Button { id: btnClean width: 300 height : 50 text : qsTr("clear items") onClicked: { for(var i =0 ; i < contentView.objArr.length; i++) { contentView.objArr[i].destroy(); } console.log("release all " + contentView.objArr.length + " views"); contentView.objArr.splice(0, contentView.objArr.length); } } Button { id: btnGC width: 300 height : 50 text : qsTr("GC") onClicked: { gc(); console.log("gc called"); } } Column { id: container spacing: 5 } } } Component { id: itemView Text { text: "I am text" color: "red" Component.onCompleted: { console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> item is created"); } Component.onDestruction: { console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> item is destroyed\n"); } } } }
the C++ code below:
int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("./res/qml/MainPage.qml"))); int res = app.exec(); return res; }
-
-
@FeelFree said in QML memory increase continuously:
ory is in two parts: C++/Js Engine. the gc() function only releas
PS: the context is stored in QQmlData with property "context", but not released in void
QQmlData::destroyed(QObject *object)
, also not releasedQQmlData::~QQmlData
.