Memory footprint monitoring in C++

Ok, so I’m trying to use getrusage() with the ru_maxrss field to monitor my memory footprint… but it’s always 0! The man file says that “not all fields (in the rusage struct) are meaningful under Linux”… are there any library functions that I can use to monitor my maximum memory usage?

Ah, my question is actually a two-part question. Is there anything I should be aware of when using memory monitoring from the top command in lieu?

Nobody?

This question may be a little too technical for this board.

What are you trying to measure? The memory footprint of your program? What about total memory usage: linked libraries, forked processes, etc. that are spawned by your program?

top is pretty accurate. The most accurate way to use top is to turn off the swapfile (temporarily) and watch the RES or RSS column. This will give you a value for just your program. The Size or VSZ column will include libraries, etc. that your program is using.

I’m not overly familiar with Linux systems, but I’ll give it a crack.

I’ve never used getrusage() and I don’t know of any standard C++ memory usage functions, but there are a couple of things to watch for with top.

  1. The system almost certainly allocates memory in some granularity, 4 kilobytes would be sensible on an x86 cpu because that’s the typical page size and it wouldn’t be worthwhile for the OS to allocate sub-page blocks (IMHO). This means that using the system’s knowledge of memory allocations will suffer a quantization error (for lack of a better term). If the system allocates in 4kb blocks, a 1 byte allocation may cause top to report an additional 4kb memory usage, where a 3kb allocation may cause no change.

  2. Some libraries use their own allocators or don’t return memory to the OS. Stlport, for example doesn’t return deallocated memory to the operating system (though this behavior may have changed), it retained deallocated memory and used that to satisfy new allocations. Therefore, your current memory usage would always be equal to your maximum memory usage.

  3. It’s best to track usage over some large amount of usages (many invocations of the program’s functionality) to detect small memory leaks and to determine the maximum memory used by a certain function.

  4. It’s not all under your control. Your program almost certainly uses some other libraries, console IO may require the library to allocate buffers and you can’t really control the size of the buffers or when they’re allocated. Similarly a database library will probably allocate buffers which are out of your immediate control, therefore you may not be able to reduce process memory usage by a large amount.

  5. Many allocators overallocate memory and most require some bookkeeping structures. You won’t find a general-purpose allocator that acutally allocates single bytes, it’s more common that they’ll allocate 4, 8, or 16 bytes for a 1 byte allocation. Performing 1,048,576 (1<<20) single byte allocations is almost certain to consume much more than 1 megabyte of memory. You can solve this problem by using a small-object allocator (allocator specialized for small allocations) or by allocating arrays of 1 byte objects (assuming that you use them as a group).

What are you trying to accomplish by monitoring your memory footprint, there tools designed to track memory leaks (i.e. Purify and ValGrind) and there are probably other (better) tools for other tasks.

Obtaining a process’ memory footprint is outside the scope of the C, C++, and X/Open/POSIX standards, so you have to be resigned to a non-portable solution.

The dynamic memory allocator (ie malloc(), etc.) of many systems have non-standard API’s for obtaining stats about dynamically allocated memory. If I recall corectly, Linux uses Doug Lea’s allocator, which has a rich set of statistics. Of course, this only measures dynamically allocated memory. It doesn’t account for memory used by the text, bss, etc. segments of your programs or shared libraries.

If you need the full memory footprint, the best bet would be to open /proc/self/stat and extract the fields you need. I believe that the “ps” and “top” programs obtain their data from /proc, so this is probably the best way to obtain the information you need.