Memory Allocation Profiling in C++

Memory profiler for C

You may want to take a look at MemProf.

How to profile memory usage?

Use massif, which is part of the Valgrind tools. massif-visualizer can help you graph the data or you can just use the ms_print command.

memory profiling for C program

Find the memory size of the object

If you want to know the size of your program on disk plus the size of text and data in RAM, on Linux/Unix you can use the size command:

$> size /bin/cat
text data bss dec hex filename
43422 1720 2472 47614 b9fe /bin/cat

The outputs of size are the memory sizes of different parts of the object file:

  • text: (code segment) executable instructions
  • data: (data segment) initialised global variables
  • bss: (block started by symbols) statically-allocated variables

The last two columns, dec and hex, are respectively the sum of the other three (the overall size) in decimal and hexadecimal.

The size you are asking for is: the output of ls (that gives you the size on disk) plus the dec part of the output of the size command that gives you the size on RAM.

See also these posts: http://www.cyberciti.biz/faq/linux-find-size-of-text-data-segment-bss-uninitialized-data/, how to know the memory footprint of my binary executable

Find the memory footprint

When referring to a software application the footprint indicates the size of the memory consumed by the running process (runtime memory requirements).

Said that, it is clear that you should check the memory footprint when the process is running. I think (and other posts confirm it) that the only real option is to use a tool like valgrind.

Profile your application with valgrind

You can profile the memory using the Massif tool. Massif is an heap profiler but can also measure the size of the stack.

valgrind --tool=massif --stacks=yes

This will give you both the heap and stack memory usage.
Then the information are stored in the file massif.out.????
that you can read with

ms_print massif.out.?????

The first output in the file is a nice chart of the memory usage during the running time.

--------------------------------------------------------------------------------
Command: ./myprog -f d5.ini
Massif arguments: --stacks=yes
ms_print arguments: massif.out.24377
--------------------------------------------------------------------------------

MB
5.292^ ##
| @ : : @@ : : # :::: : :
| @:::: :: : :@:@@::::::::::::@ :::::::::::::# ::::@::::@::::::::
| @:: ::: :::::::::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| @:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| @:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| @:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| @:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| @:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| @:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| @@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| @@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| ::@@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| : @@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| : @@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| : @@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| : @@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| : @@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| : @@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
| : @@:: ::: : :::: ::@:@ ::: :: :::: @ :: ::: ::::::# ::::@: ::@::::::::
0 +----------------------------------------------------------------------->Gi
0 1.030

The details are stored in the file, inside different tables.
To fully understand the output refers to the Valgrind manual page which seems really clear.

The option to trace the children is: --trace-children=yes

Interesting, it seems that there is no "actual memory usage of a process":
https://unix.stackexchange.com/questions/164653/actual-memory-usage-of-a-process.

Profile per-function memory usage in C in Unix

As OP highlighted, each class of storage can be measured with different tool. In the old days (C90), this was relativel simple. Nowadays, much more complex ...

Static Memory:

Static memory (static or global), can be measured at the object file level (.o) using the size tool. This will include the memory for all static data in the file - potentially multiple functions. For example the function in o5 need 120+512 (data+bss)

size o5.o
text data bss dec hex filename
757 512 120 1389 56d o5.o

Automatic Variables

Measuring automatic variables ("local") is more tricky. Before C99, allocation was fixed at compiled time (with the exception of the now alloca calls). It was possible to inspect the assembly generated code to find out how much stack space is allocated for a function. With C99, which allows VLA, this is no longer possible, for example

void f(int n) {
int a[n+3] ; // Variable Length Array, size calculated at run time.
}

Also, with optimizations, many compiler are able to detect that two variables can share the same space, as they are not used at the same time. For example, most compilers can tell that x and y can share the same space.

void f(int n) {

for (int i=0 ; ... ; ... ) {
int x[30] ;
} ;

for (int j=0 ; ... ; ... ) {
int y[30] ;
} ;
}

In theory, one can sample the stack size during run time, and try to determine 'typical' size of a function with VLA. For functions without VLA, ofter possible to extract the data from the generated assembly. Mileage will vary.

Dynamic Variables

For Dynamic memory allocations (malloc, and friends) - runtime tool are best set to capture how much memory is allocated. However, most tools will not be able to measure actual dynamic usage - they will usually perform analysis of the heap at a specific point of time, which could be more or less than what the function is actually using.

profiling maximum memory usage in C application - linux

Take a look at Massif: http://valgrind.org/docs/manual/ms-manual.html

How to profile memory usage of a C program

You could wrap all your calls to free and malloc with your own functions in which you also supply for instance in which file and at what line number each allocation is done. From this information it's easy to see what memory is being used where.

Is it possible to profile memory only by storing allocated pointer address in C++?

Is it true, that in C++ I can be sure that pointer passed to the operator delete (or free()) always will be the one previously allocated?

Yes, this is true. It could also be a null pointer, in which case your function should do nothing.

The behavior of the standard library implementation of this function is undefined unless ptr is a null pointer or is a pointer previously obtained from the standard library implementation of operator new...

Since most code is written for the standard library implementation of operator new/delete, it does not pass other pointers to operator delete.

It is possible for someone to write a class with an overloaded operator new and operator delete which do not have this requirement. In that case, it won't call your custom allocator, either.



Related Topics



Leave a reply



Submit