Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Minimizing memory footprint in C programs

What are my options for minimizing memory footprint in C programs on Linux (*nix)?

As far as I know libc malloc() is using either brk() or mmap(). Memory allocated with brk() usually cannot be returned because of memory fragmentation.

My program should work 24/7 and it does a lot of malloc()-s and free()-s. After starting, RSS goes up to approximately 100Mb. It is too much, because I know for sure that in any particular moment there is less than 100 Mb data in memory.

Probably it is brk() fragmentation issue.

So, what re my options here?

Should I use another malloc() implementation, which uses only mmap()? Should I do something else? Is there something I can read concerning memory footprint issue?

Thanks.

like image 774
Marko Kevac Avatar asked Nov 27 '10 15:11

Marko Kevac


2 Answers

If your program has so many malloc and free calls that you get this kind of fragmentation, using mmap for each allocation will be hopelessly slow. Instead you need to measure what's causing the memory fragmentation and fix it. First I would use a tool like valgrind to make sure it's not actually a memory leak/corruption issue causing the excessive memory usage. Then, to confirm that the cause of the problem is fragmentation, I would wrap all calls to malloc and free with your own wrapper that increments and decrements a "total allocated byte count" variable so you can, at any point, compare the theoretical and actual memory consumption.

If it turns out fragmentation is the problem, a good first step is looking at why you're making so many small, short-lived allocations. If you can eliminate them and instead allocate all the memory a particular task/data object will need in a single block, then chop it up yourself, you'll not only get rid of the worst fragmentation but also improve the performance of your code quite a bit. Each call to malloc or free incurs a good bit of overhead, especially in a threaded environment where synchronization/locking is necessary. Keeping all associated data together in a single allocated block can also reduce or eliminate the need to write special code to free structures containing pointers; a single call to free may often suffice (though for the sake of keeping the implementation opaque you should still wrap this with a foo_free function).

like image 112
R.. GitHub STOP HELPING ICE Avatar answered Oct 29 '22 04:10

R.. GitHub STOP HELPING ICE


Unless you are allocating fixed sized blocks - or performing some sort of periodic garbage collection - you memory footprint is likely to grow beyond what is required due to fragmentation.

free() cannot return memory to the OS unless full pages not used.

My suggestion would be to use a slab allocation scheme. Pre-allocate several pools of memory. Each pool will be used with objects of similar size (ideally identical size). This way you avoid fragmentation and keep your RSS footprint constant (albeit bigger than absolutely necessary due to preallocation).

like image 30
nimrodm Avatar answered Oct 29 '22 03:10

nimrodm