How to manage memory usage of an application?
-
Lets say my application has a label and other widgets that dont need to be reffered.
When simply runned it takes10.7 mb of memorywhen i set the pixmap of this label to an image from the resource file, memory goes to 11.3 mb
BUT when i clear the pixmap of the label, memory STAYS on 11.3 mb
the same goes with dialogs when i exec them.....Don't know if it's an ubuntu bug, or i am just doing something wrong..
-
Try to use Valgrind. It will tell you where you lose your memory.
What do you mean by clearing the pixmap of the label? As I understand you just remove it but you don't delete the pointer.
-
Note that often it is seen as more efficient to keep the memory assigned to the process (your application) than to actually signal to the OS that it's free again. After all, during the lifetime of the application, that memory might be needed again some time later. For example, QMap on the heap doesn't free up memory that it occupied if you delete the map.
-
[quote author="Leon" date="1375280427"]Don't know if it's an ubuntu bug, or i am just doing something wrong..[/quote]
Neither one thing nor the other. It's quite possible that QLabel allocates additional memory when you assign the the pixmap for the first time, but does not release that memory immediate when you clear the pixmap. It might keep that memory for future use, so it does not have to be reallocated when you assign a new pixmap. A performance optimization. As long as QLabel releases the memory when the object is destroyed, this is not a memory leak.
Pretty much like:
@Foo::Foo(void)
{
m_data = NULL;
}Foo::~Foo(void)
{
if(m_data) { delete m_data; } //Free on destruction
}void Foo::set(const Bar &x)
{
if(!m_data) { m_data = new Bar(); } //Allocate on first use
m_data->assign(bar);
}void Foo::clear(void)
{
if(m_data) { m_data->clear(); }
}@--
You can also try this: set a pixmap, then clear it, then set pixmap again. And so on. Do this in a loop, many many times. If you see memory go up continuously (until application crashes with "out of memory"), then you have a memory leak. If it goes up once and then stays at that level, you are fine.
--
Another thing to consider is how the memory manager works:
Applications request "heap" memory from the C Runtime's memory manager. And the C Runtime, in turn, requests memory pages form the OS. When the application requests more memory, the memory manager either has enough free memory in its pool - or it must request more memory pages from the OS. But: When the application releases some heap memory, the memory manager does not necessarily free memory pages immediately! It might keep them in the pool for future use. That's because Syscall's are expensive! Consequently, you might see the memory usage go up when the application allocates N bytes, but not see the memory usage go down by the same amount (immediately) when the application releases those N bytes again.
-
That really depends on what you are doing. In general I would say it is good practice to free memory you allocate and not let the OS clean up after you. It might be more efficient for lets say look up tables and such staff but these objects you will need over the entire lifetime of your application and you would not delete it anyway. Objects which will be created on e. g. user interaction must get deleted or otherwise the memory consumption will kill your app. Also the additional code to determine if you will need an object again or if you can reuse might also be everything else but efficient.
-
[quote author="butterface" date="1375307676"]In general I would say it is good practice to free memory you allocate and not let the OS clean up after you. (...) must get deleted or otherwise the memory consumption will kill your app. Also the additional code to determine if you will need an object again or if you can reuse might also be everything else but efficient.[/quote]
In case you're referring to my post: That's just the way most containers in most libraries, including Qt and the standard C++ library work. And I guess lots of experienced people have thought about the pros and cons. So we as users of those libraries can't choose anyway, we just need to know about that kind of memory management
-
[quote author="butterface" date="1375307676"]That really depends on what you are doing. In general I would say it is good practice to free memory you allocate and not let the OS clean up after you. It might be more efficient for lets say look up tables and such staff but these objects you will need over the entire lifetime of your application and you would not delete it anyway.[/quote]
What you describe indeed would be a memory leak - though not necessarily one that keeps on growing and will cause failure. But what many "container" objects do is something completely different! Those objects internally allocate memory to store data. When new data is added, more memory is allocated (the buffer grows). But when the data is cleared, the internal buffer is not deallocated (immediately). It is kept for future use. But that is not a memory leak at all! The container object still has a pointer to that memory and eventually is going to use that memory again - when new data is added. Also, when the container object is destroyed, its destructor will free the buffer.
-
[quote author="DerManu" date="1375314101"][quote author="MuldeR" date="1375313162"]Also, when the container object is destroyed, its destructor will free the buffer.[/quote]
No, this is not necessarily true, see QMap.[/quote]
If the container object , e.g. QMap, does not release the memory when a "clear" operation is performed on the container object, that is fine. The container will keep that memory and reuse when you add items again.
But if the container does not release its internal buffer, when the container object is destroyed, that would be a memory leak and thus a serious bug! That's because after the container object has been destroyed, the memory used for its internal buffer would be lost and can never be used again...
(The above consideration leaves out "implicit sharing". When "implicit sharing" is used, the memory for the internal buffer would be released when the last object sharing the same buffer gets destroyed)
-
[quote author="MuldeR" date="1375314906"]That's because after the container object has been destroyed, the memory used for its internal buffer would be lost and can never be used again...[/quote]
Test it yourself.
@ QMap<int, QString> *test = new QMap<int, QString>;
for (int i=0; i<20000000; ++i)
test->insert(i, "abcdefghijklmnop");
delete test;@
You will see, that the memory footprint will stay large, no matter whether you have the delete line or not.I suspect some singleton (either in QApplication or a lower level allocation method) holds the memory for the process.
-
Well, I tried with that code:
@qsrand((uint)time(NULL));
std::cerr << "Ready." << std::endl;
getchar();for(;;)
{
QMap<int,int> *test = new QMap<int,int>();
for(int i = 0; i < 12800000; i++)
{
test->insert(i, qrand());
}std::cerr << "Done." << std::endl;
getchar();delete test;
test = NULL;std::cerr << "Cleared." << std::endl;
getchar();
}@The memory usage ("Private Bytes") goes up from about 1 MB before the QMap to about 310 MB when the map has been filled with data. And it does go down again when the map is destroyed! Though it doesn't go down to 1 MB, but to something like 4 MB. I can do many iterations and it always goes down to 4 MB or a little more again. So everything works as expected.
Now why it goes down to 4 MB and not 1 MB? This effect might be explained by the C Runtime's memory manager, which doesn't give all memory pages back to the OS, but keeps a certain amount in its pool for future allocations. It's also possible that Qt implements its own memory pool on top of the C Runtime. To be honest, I haven't checked all the internals of QMap...
--
Update:
Calling "_heapmin()":http://tinyurl.com/heapmin, which tells the C Runtime to release all unused heap memory to the OS, further reduces the memory usage after the QMap has been destroyed. From about 5 MB to about 2.5 MB. So at least some of that memory was still occupied/reserved by the C Runtime...
-
Yes, DerManu and MuldeR, I think all three of us are right. ;)
Of course not freeing memory is not a leak if you still know where your memory is. But in this case you will need some additional memory management because what happens if I create a buffer of lets say 15 MB on a system with 16 MB, "free" that memory by deleting the map and then try to allocate another 10 MB? Mathematically this must work but if you don't have smart enough buffers this will crash your system.