I have a C++ application where I sometimes require a large buffer of POD types (e.g. an array of 25 billion float
s) to be held in memory at once in a contiguous block. This particular memory organization is driven by the fact that the application makes use of some C APIs that operate on the data. Therefore, a different arrangement (such as a list of smaller chunks of memory like std::deque
uses) isn't feasible.
The application has an algorithm that is run on the array in a streaming fashion; think something like this:
std::vector<float> buf(<very_large_size>);
for (size_t i = 0; i < buf.size(); ++i) do_algorithm(buf[i]);
This particular algorithm is the conclusion of a pipeline of earlier processing steps that have been applied to the dataset. Therefore, once my algorithm has passed over the i
-th element in the array, the application no longer needs it.
In theory, therefore, I could free that memory in order to reduce my application's memory footprint as it chews through the data. However, doing something akin to a realloc()
(or a std::vector<T>::shrink_to_fit()
) would be inefficient because my application would have to spend its time copying the unconsumed data to the new spot at reallocation time.
My application runs on POSIX-compliant operating systems (e.g. Linux, OS X). Is there any interface by which I could ask the operating system to free only a specified region from the front of the block of memory? This would seem to be the most efficient approach, as I could just notify the memory manager that, for example, the first 2 GB of the memory block can be reclaimed once I'm done with it.
Is it possible to partially free dynamically-allocated memory on a POSIX system?
You can not do it using malloc()
/realloc()
/free()
.
However, you can do it in a semi-portable way using mmap()
and munmap()
. The key point is that if you munmap()
some page, malloc()
can later use that page:
mmap()
;munmap()
for regions that you don't need anymore.The portability issues are:
MAP_ANONYMOUS
or MAP_ANON
flag. Other systems provide special device file that can be mapped for this purpose. Linux provides both.munmap()
a page, malloc()
will be able to use it. But I think it'll work an all systems that have mmap()
/unmap()
.Update
If your memory region is so large that most pages surely will be written to swap, you will not loose anything by using file mappings instead of anonymous mappings. File mappings are specified in POSIX.