Reputation: 16121
I have an app that takes about 20 MB of ram. In an seldom used algorithm it (std::vector) temporarily allocates 250 MB. After the deallocation the systemmonitor still shows this usage. How can I release the memory back to the system?
Upvotes: 5
Views: 2740
Reputation: 59670
That's not how virtual memory and the heap manager work (at least not on Windows).
On Windows, you have 2 levels of memory management. The most basic form of memory management is done by the operating system. From the operating system, you can request memory via VirtualAlloc()
. VirtualAlloc()
gives you memory in multiples of granularity. A typical value for granularity is 64 kB.
Understand that correctly: if you request 1 Byte from VirtualAlloc()
, you can do that. But: you will waste a lot of memory, because the block that the function returns will be at least 64 kB.
You might ask: "WTF? Why?". Imagine the operating system would be able to keep track of each individual byte that you allocate. Storing the address of each byte that is allocated would require more memory than the actual memory available for you. So there has to be a compromise.
That's why Windows has another mechanism: the Windows Heap Manager. The Windows Heap Manager takes large 64 kB blocks of virtual memory (via VirtualAlloc()
, the same call) and then do some clever management for you.
If you request 1 byte from the Windows Heap Manager, you get a pointer to 1 usable byte. Around that memory location will be some overhead, for which I don't want to go into details. It would require to explain the terms Heap, Segment, Block, Preallocation Metadata and Postallocation Metadata. You can read about all that in the Windows Internals book by Mark Russinovich.
Just think about it this way: The heap manager will further break down the 64 kB block into regions for allocations of different sizes. And somewhere in that 64 kB block it will store information on how the memory is used.
If you free()
or delete
one or several pointers, this memory is very likely still not free. a) it still contains the management structures of the Windows Heap Manager and b) it likely contains at least one pointer.
So, even if only 1 pointer to 1 byte is left in that memory region, the Windows Heap Manager cannot return the 64 kB block back to the operating system.
Other things to consider (but I don't know for sure): the Windows Heap Manager probably does not check at every free()
or delete
whether all memory of the 64 kB block is freed. a) calculating that might take long (especially for a language like C++) and b) probably you're going to malloc()
or new
a byte in the near future anyway. So why should the heap Manager return the memory it already has back to the OS?
All of the above is independent of the paging process. Unused memory can be paged out in chunks of page size, which is 4 kB typically. "Page out" means "written to the disk into the pagefile.sys
".
Why is that important? It means that virtual memory does not necessarily use the fast and valuable physical RAM.
So you freed 250 MB? Let the OS decide whether it can keep those 250 MB in physical RAM or whether it gets paged out. If your application requests new virtual memory, it may benefit from the fact that it happens to be there for you for free (i.e. without a call to VirtualAlloc()
).
Upvotes: 0
Reputation: 43337
Use mmap() or VirtualAlloc() to allocate and release memory. This returns it to the OS immediately.
In order to use with std::vector, you'll need to provide it a std::allocator. You might find it easier to hand-roll your own vector w/ placement new and direct destructor invocation.
Normally the system heap allocators handle this correctly for you; however it looks like you found a case where they do not.
Upvotes: 4
Reputation: 385405
You can't, and shouldn't.
Virtual memory allocation is complicated, and cannot be sufficiently understood by simply watching a number in System Monitor. It may appear as if a process is using more memory than it should, but this is just an artefact of the way virtual memory addressing works.
Rest assured, if you have freed this memory properly, and the OS really needed it back, it would be reassigned.
The only real actionable point here is to stop using System Monitor as if it were an accurate measure of physical RAM in use by your process!
Upvotes: 6