Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Huge std::vector<std::vector> does not release all memory on destruction [duplicate]

Tags:

When using a very large vector of vectors we've found that part of the memory is not released.

#include <iostream> #include <vector> #include <unistd.h>  void foo() {     std::vector<std::vector<unsigned int> > voxelToPixel;     unsigned int numElem = 1<<27;     voxelToPixel.resize( numElem );      for (unsigned int idx=0; idx < numElem; idx++)         voxelToPixel.at(idx).push_back(idx);  }  int main() {     foo();     std::cout << "End" << std::endl;     sleep(30);     return 0; } 

That leaves around 4GB of memory hanging until the process ends.

If we change the for line to

for (unsigned int idx=0; idx < numElem; idx++)     voxelToPixel.at(0).push_back(idx); 

the memory is released.

Using gcc-4.8 on a linux machine. We've used htop to track the memory usage on a computer with 100 GB of RAM. You will need around 8 GB of RAM to run the code. Can you reproduce the problem? Any ideas on why that is happening?

EDIT: We've seen that that does not happen in a Mac (with either gcc or clang). Also, in linux, the memory is freed if we call foo two times (but happens again the third time).

like image 986
quimnuss Avatar asked Sep 24 '14 15:09

quimnuss


People also ask

Does std::vector clear free memory?

No, memory are not freed. In C++11, you can use the shrink_to_fit method for force the vector to free memory. Show activity on this post.

Does std::vector allocate memory?

As mentioned above, std::vector is a templated class that represents dynamic arrays. std::vector typically allocates memory on the heap (unless you override this behavior with your own allocator). The std::vector class abstracts memory management, as it grows and shrinks automatically if elements are added or removed.

How much memory does std::vector use?

So there is no surprise regarding std::vector. It uses 4 bytes to store each 4 byte elements.

Does vector have contiguous memory?

Vectors are assigned memory in blocks of contiguous locations. When the memory allocated for the vector falls short of storing new elements, a new memory block is allocated to vector and all elements are copied from the old location to the new location. This reallocation of elements helps vectors to grow when required.


1 Answers

Small allocations (up to 128kb by default, I think) are managed by an in-process heap, and are not returned to the OS when they're deallocated; they're returned to the heap for reuse within the process. Larger allocations come directly from the OS (by calling mmap), and are returned to the OS when deallocated.

In your first example, each vector only needs to allocate enough space for a single int. You have a hundred million small allocations, none of which will be returned to the OS.

In the second example, as the vector grows, it will make many allocations of various sizes. Some are smaller than the mmap threshold, these will remain in the process memory; but, since you only do this to one vector, that won't be a huge amount. If you were to use resize or reserve to allocate all the memory for each vector before populating it, then you should find that all the memory is returned to the OS.

like image 167
Mike Seymour Avatar answered Sep 21 '22 13:09

Mike Seymour