Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the amount of memory c++ is allocating

Tags:

I'm trying to develop a better understanding of the amount of memory that is allocated on the heap in c++. I've written a small test program which basically does nothing else than fill a number of 2D vectors. I'm running this on a linux 64bit VM and use valgrind's massif tool in order to profile the memory.

The environment I'm running this test on: Linux VM running in VirtualBox on Win10. VM configuration: Base memory: 5248MB, 4CPU's, cap At 100%, disk-type VDI (dynamically alocated storage).

c++ memory profiling test program:

/**  * g++ -std=c++11 test.cpp -o test.o  */  #include <string> #include <vector> #include <iostream>  using namespace std;  int main(int argc, char **arg) {     int n = stoi(arg[1]);     vector<vector<int> > matrix1(n);     vector<vector<int> > matrix2(n);     vector<vector<int> > matrix3(n);     vector<vector<int> > matrix4(n);     vector<vector<int> > matrix5(n);     vector<vector<int> > matrix6(n);     vector<vector<int> > matrix7(n);     vector<vector<int> > matrix8(n);      for (int i=0; i<n; ++i) {         for (int j=0; j<n; ++j) {             matrix1[i].push_back(j);         }     }      for (int i=0; i<n; ++i) {         for (int j=0; j<n; ++j) {             matrix2[i].push_back(j);         }     }      for (int i=0; i<n; ++i) {         for (int j=0; j<n; ++j) {             matrix3[i].push_back(j);         }     }      for (int i=0; i<n; ++i) {         for (int j=0; j<n; ++j) {             matrix4[i].push_back(j);         }     }      for (int i=0; i<n; ++i) {         for (int j=0; j<n; ++j) {             matrix5[i].push_back(j);         }     }      for (int i=0; i<n; ++i) {         for (int j=0; j<n; ++j) {             matrix6[i].push_back(j);         }     }      for (int i=0; i<n; ++i) {         for (int j=0; j<n; ++j) {             matrix7[i].push_back(j);         }     }      for (int i=0; i<n; ++i) {         for (int j=0; j<n; ++j) {             matrix8[i].push_back(j);         }     } } 

I run the following bash script in order to extract memory profiles at different values of n (test.o is the program above, compiled with g++ -std=c++11, g++ is version 5.3.0)

valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 250 valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 500 valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 1000 valgrind --tool=massif --massif-out-file=massif-n2000.txt ./test.o 2000 valgrind --tool=massif --massif-out-file=massif-n4000.txt ./test.o 4000 valgrind --tool=massif --massif-out-file=massif-n8000.txt ./test.o 8000 valgrind --tool=massif --massif-out-file=massif-n16000.txt ./test.o 16000 valgrind --tool=massif --massif-out-file=massif-n32000.txt ./test.o 32000 

This gives me the following results:

|--------------------------------| | n     | peak heap memory usage | |-------|------------------------| | 250   | 2.1 MiB                |          | 500   | 7.9 MiB                | | 1000  | 31.2 MiB               | | 2000  | 124.8 MiB              | | 4000  | 496.5 MiB              | | 8000  | 1.9  GiB               | | 16000 | 6.2 GiB                | | 32000 | 6.1 GiB                | |--------------------------------| 

Each matrix will be n^2 in size, I have a total of 8 matrices, hence I expected a memory usage to be around f(n) = 8 * n^2.

Question 1 From n=250 to n=8000, why is the memory usage more or less multiplied by 4 at n*=2 ?

From n=16000 to n=32000 something very strange is happening because valgrind actually reports a memory decrease.

Question 2 What is happening between n=16000 and n=32000, how can it be possible that heap memory is less, while in theory more data should be allocated?

See below the massif-visualizer output for n=16000 and n=32000.

n=16000 n=32000

like image 829
Gio Avatar asked Aug 21 '17 13:08

Gio


People also ask

How the memory is allocated in C?

In C, dynamic memory is allocated from the heap using some standard library functions. The two key dynamic memory functions are malloc() and free(). The malloc() function takes a single parameter, which is the size of the requested memory area in bytes. It returns a pointer to the allocated memory.

When the memory is allocated for a variable in C?

When a variable is declared compiler automatically allocates memory for it. This is known as compile time memory allocation or static memory allocation. Memory can be allocated for data variables after the program begins execution. This mechanism is known as runtime memory allocation or dynamic memory allocation.

What is the allocation of memory?

Memory allocation is the process of reserving a partial or complete portion of computer memory for the execution of programs and processes. Memory allocation is achieved through a process known as memory management.

How much memory is allocated to a structure in C?

There are 5 members declared for structure in above program. In 32 bit compiler, 4 bytes of memory is occupied by int datatype. 1 byte of memory is occupied by char datatype and 4 bytes of memory is occupied by float datatype.


1 Answers

1) Because the sizes of your matrix vectors (and thus their memory footprint) grow as n2, so doubling n leads to quadrupling of memory usage. Any deviations from the exact relationship (as opposed to asymptotic) are due to different factors (e.g. metadata used by malloc / std::allocator, block size doubling method used by vector)

2) You are beginning to run out of memory, so Linux is starting to page some; use --pages-as-heap=yes if you want to see the total (active + paged) memory usage. (Source: http://valgrind.org/docs/manual/ms-manual.html)

like image 93
meowgoesthedog Avatar answered Sep 25 '22 14:09

meowgoesthedog