The Qml Memory leak
-
After I used javascript dynamic create qml object . I use destory function . But I see the memory has no decrease . When I create an new qml object . The memory only increase . Can you tell me . How to destory the qml object . And how to release the memory of qml object . Thanks !
-
Is it increasing every time you create the object ?. Men management is not straight forward like C++. It allocates in chunk, manages with available memory, if this chunk is exhausted, it should allocated new chunk. It follows Javascript memory management methodology. So when you destroy you many not see immediate decrease. At the same time every time you allocated object it should not increase every time.
-
Is it increasing every time you create the object ?. Men management is not straight forward like C++. It allocates in chunk, manages with available memory, if this chunk is exhausted, it should allocated new chunk. It follows Javascript memory management methodology. So when you destroy you many not see immediate decrease. At the same time every time you allocated object it should not increase every time.
@dheerendra When I destory the qml object . It doesn't to release memory immediately . But I create the qml object again , It will increase 100K memory . How can we take the initiative to release these memory .
Our platform is arm , Qt Version is Qt5.8
-
@dheerendra When I destory the qml object . It doesn't to release memory immediately . But I create the qml object again , It will increase 100K memory . How can we take the initiative to release these memory .
Our platform is arm , Qt Version is Qt5.8
@Mr-.Wu How are you destroying and creating the qml objects?
Are these true memory leaks, as in they are still allocated when you exit the application?
@dheerendra is correct in what he says. You will not see immediate changes in freed memory with javascript. You don't even see that with C++ any more. OSes are very good at handling memory and freeing/allocating pages is expensive so it isn't done until it is truly needed.
You probably don't have a real memory leak at all.
-
@Mr-.Wu How are you destroying and creating the qml objects?
Are these true memory leaks, as in they are still allocated when you exit the application?
@dheerendra is correct in what he says. You will not see immediate changes in freed memory with javascript. You don't even see that with C++ any more. OSes are very good at handling memory and freeing/allocating pages is expensive so it isn't done until it is truly needed.
You probably don't have a real memory leak at all.
@ambershark I used javasript to create the qml object . such as Qt.createComponent and Qt.createObject functions . The qml object is a ApplicationWindow object . When I need close the ApplicationWindow . I call the object.destroy() function .
I do a test that use javascript to create qml object , 2seconds later, call destory it . I have test one hour . The memory increase 20M .
-
@Mr-.Wu How are you destroying and creating the qml objects?
Are these true memory leaks, as in they are still allocated when you exit the application?
@dheerendra is correct in what he says. You will not see immediate changes in freed memory with javascript. You don't even see that with C++ any more. OSes are very good at handling memory and freeing/allocating pages is expensive so it isn't done until it is truly needed.
You probably don't have a real memory leak at all.
@ambershark I used the javascript to create qml object like this:
A.qml
ApplicationWindow
{
id:launcherWindow;
visible: true;
x:0;
y:0;
.........
}B.qml
ApplicationWindow
{
id:mRootWindow;
visible: true;
width:CommonJS.ScreenWitdh;
height: CommonJS.ScreenHeight;
flags:Qt.FramelessWindowHint;
......
}I define a function in a javascript file . like this:
function createQmlObject(qml_file)
{
var subWindow;
var component = Qt.createComponent(qml_file);
if (component.status == Component.Ready)
return creationWindow();
else
{
component.statusChanged.connect(creationWindow);
return null;
}function creationWindow() { var parent = launcherWindow; if (component.status == Component.Ready) { subWindow = component.createObject(parent, {"x": 0, "y": 0}); if (subWindow == null) console.log("Create Window Error"); } else if (component.status == Component.Error) { subWindow = null; console.log("Create Window Error Loading Component:", component.errorString()); return null; } return subWindow; }
}
function destoryQmlObject(objectWindow)
{
if(objectWindow == null)
{
console.log("the window is null . can't destory it .");
return;
}
objectWindow.destroy();
}In the A.qml , I call the createQmlObject function to create B.qml . When the B.qml need close , call destoryQmlObject function .
-
@ambershark I used the javascript to create qml object like this:
A.qml
ApplicationWindow
{
id:launcherWindow;
visible: true;
x:0;
y:0;
.........
}B.qml
ApplicationWindow
{
id:mRootWindow;
visible: true;
width:CommonJS.ScreenWitdh;
height: CommonJS.ScreenHeight;
flags:Qt.FramelessWindowHint;
......
}I define a function in a javascript file . like this:
function createQmlObject(qml_file)
{
var subWindow;
var component = Qt.createComponent(qml_file);
if (component.status == Component.Ready)
return creationWindow();
else
{
component.statusChanged.connect(creationWindow);
return null;
}function creationWindow() { var parent = launcherWindow; if (component.status == Component.Ready) { subWindow = component.createObject(parent, {"x": 0, "y": 0}); if (subWindow == null) console.log("Create Window Error"); } else if (component.status == Component.Error) { subWindow = null; console.log("Create Window Error Loading Component:", component.errorString()); return null; } return subWindow; }
}
function destoryQmlObject(objectWindow)
{
if(objectWindow == null)
{
console.log("the window is null . can't destory it .");
return;
}
objectWindow.destroy();
}In the A.qml , I call the createQmlObject function to create B.qml . When the B.qml need close , call destoryQmlObject function .
@Mr-.Wu Ok that's interesting.. Can you try running this through something like valgrind to see if you have a real memory leak. If the memory is growing over an hour you may have a real memory leak. The destroy may not be actually destroying the object. I'm not sure how the javascript works for that, but it may just put it on a destruction list for when a reference count hits 0 or something. Then that ref count never hits 0 so it doesn't get cleaned up. Just guessing here.
Valgrind will tell you if you do, when you exit your app you will get something like this:
==10819== ==10819== HEAP SUMMARY: ==10819== in use at exit: 0 bytes in 0 blocks ==10819== total heap usage: 317 allocs, 317 frees, 138,318 bytes allocated ==10819== ==10819== All heap blocks were freed -- no leaks are possible ==10819== ==10819== For counts of detected and suppressed errors, rerun with: -v ==10819== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
That will tell you if there are actual leaks if it's just not cleaning up objects because it has a block of memory allocated.
-
@Mr-.Wu Ok that's interesting.. Can you try running this through something like valgrind to see if you have a real memory leak. If the memory is growing over an hour you may have a real memory leak. The destroy may not be actually destroying the object. I'm not sure how the javascript works for that, but it may just put it on a destruction list for when a reference count hits 0 or something. Then that ref count never hits 0 so it doesn't get cleaned up. Just guessing here.
Valgrind will tell you if you do, when you exit your app you will get something like this:
==10819== ==10819== HEAP SUMMARY: ==10819== in use at exit: 0 bytes in 0 blocks ==10819== total heap usage: 317 allocs, 317 frees, 138,318 bytes allocated ==10819== ==10819== All heap blocks were freed -- no leaks are possible ==10819== ==10819== For counts of detected and suppressed errors, rerun with: -v ==10819== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
That will tell you if there are actual leaks if it's just not cleaning up objects because it has a block of memory allocated.
@ambershark When I create an new project . I do a test with VLD. The project named MyTest . When I used a button to quite the application . the qml memory leaks . the log like this :
Visual Leak Detector read settings from: C:\Program Files (x86)\Visual Leak Detector\vld.ini
Visual Leak Detector Version 2.5.1 installed.
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 3 at 0x0000000000289540: 91 bytes ----------
Leak Hash: 0x3FCB8D57, Count: 1, Total 91 bytes
Call Stack (TID 13400):
ucrtbased.dll!malloc()
f:\dd\vctools\crt\vcstartup\src\heap\new_array.cpp (16): MyTest.exe!operator new
c:\users\qt\work\qt\qtbase\src\winmain\qtmain_win.cpp (107): MyTest.exe!wideToMulti() + 0xD bytes
c:\users\qt\work\qt\qtbase\src\winmain\qtmain_win.cpp (120): MyTest.exe!WinMain() + 0x15 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (99): MyTest.exe!invoke_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (253): MyTest.exe!__scrt_common_main_seh() + 0x5 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (296): MyTest.exe!__scrt_common_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_winmain.cpp (17): MyTest.exe!WinMainCRTStartup()
kernel32.dll!BaseThreadInitThunk() + 0xD bytes
ntdll.dll!RtlUserThreadStart() + 0x21 bytes
Data:
2D 71 6D 6C 6A 73 64 65 62 75 67 67 65 72 3D 70 -qmljsde bugger=p
6F 72 74 3A 33 33 32 34 36 2C 62 6C 6F 63 6B 2C ort:3324 6,block,
73 65 72 76 69 63 65 73 3A 44 65 62 75 67 4D 65 services :DebugMe
73 73 61 67 65 73 2C 51 6D 6C 44 65 62 75 67 67 ssages,Q mlDebugg
65 72 2C 56 38 44 65 62 75 67 67 65 72 2C 51 6D er,V8Deb ugger,Qm
6C 49 6E 73 70 65 63 74 6F 72 00 lInspect or......Visual Leak Detector detected 1 memory leak (143 bytes).
Largest number used: 363 bytes.
Total allocations: 363 bytes.
Visual Leak Detector is now exiting.
button1.onClicked: {
Qt.quit();
} -
@ambershark When I create an new project . I do a test with VLD. The project named MyTest . When I used a button to quite the application . the qml memory leaks . the log like this :
Visual Leak Detector read settings from: C:\Program Files (x86)\Visual Leak Detector\vld.ini
Visual Leak Detector Version 2.5.1 installed.
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 3 at 0x0000000000289540: 91 bytes ----------
Leak Hash: 0x3FCB8D57, Count: 1, Total 91 bytes
Call Stack (TID 13400):
ucrtbased.dll!malloc()
f:\dd\vctools\crt\vcstartup\src\heap\new_array.cpp (16): MyTest.exe!operator new
c:\users\qt\work\qt\qtbase\src\winmain\qtmain_win.cpp (107): MyTest.exe!wideToMulti() + 0xD bytes
c:\users\qt\work\qt\qtbase\src\winmain\qtmain_win.cpp (120): MyTest.exe!WinMain() + 0x15 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (99): MyTest.exe!invoke_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (253): MyTest.exe!__scrt_common_main_seh() + 0x5 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (296): MyTest.exe!__scrt_common_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_winmain.cpp (17): MyTest.exe!WinMainCRTStartup()
kernel32.dll!BaseThreadInitThunk() + 0xD bytes
ntdll.dll!RtlUserThreadStart() + 0x21 bytes
Data:
2D 71 6D 6C 6A 73 64 65 62 75 67 67 65 72 3D 70 -qmljsde bugger=p
6F 72 74 3A 33 33 32 34 36 2C 62 6C 6F 63 6B 2C ort:3324 6,block,
73 65 72 76 69 63 65 73 3A 44 65 62 75 67 4D 65 services :DebugMe
73 73 61 67 65 73 2C 51 6D 6C 44 65 62 75 67 67 ssages,Q mlDebugg
65 72 2C 56 38 44 65 62 75 67 67 65 72 2C 51 6D er,V8Deb ugger,Qm
6C 49 6E 73 70 65 63 74 6F 72 00 lInspect or......Visual Leak Detector detected 1 memory leak (143 bytes).
Largest number used: 363 bytes.
Total allocations: 363 bytes.
Visual Leak Detector is now exiting.
button1.onClicked: {
Qt.quit();
}@Mr-.Wu As I figured though.. you only leaked 143 bytes, not 20+ MB.
So you don't have a real memory leak. That is just how the engine is using the memory for you creating and deleting multiple components. It probably has a large memory pool or pages allocated and will use those before cleaning them up to get new memory.
I don't think you will get the C++ level memory control you want out of Qml since it is essentially javascript. I would recommend not creating and deleting a bunch of objects, instead maybe hide them when they aren't in use with something like
myObj.visible = false
.Edit: oh and that memory leak probably isn't real. It came from the crt which is known to "leak" on exit of applications. It's not a real leak though it just didn't clean the memory before the memory checker saw the exit of the application.
-
Need recommendation on tools to Detect memory leak in Qml file. Valgrind 's massif is precise and helps in c++ code but for those in Qml, the allocation is masked through Qml Engine and Js Engine framework components.