Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

My favourite example of memory allocation anti-patterns:

A decade or so ago I worked on a GUI and we needed a Type 1 font parser. Freetype was not a good fit to our (very memory constrained, slow) platform. I was suprised though, how slow the library was, and did some profiling. First thing I noticed was a huge number of malloc() calls. And they were all small. A huge portion of them were only 4 bytes. The malloc() implementation on our platform had an overhead of at least 12 bytes per allocation, so not only was it slow, it also wasted a ludicrous amount of memory.

All in all there were multiple allocations per glyph despite the fonts being loaded and unloaded as a single unit. Yikes.

Since we were in a rush, my hacky fix was a search/replace for malloc()/free() to special a special version of malloc that would just grab the next free chunk from a pool, or if the pool was full allocate another 4KB block and start allocating from that, and nothing for free, and then I added code to initialise the pool and free it to the open/close parts of the font API.

The result was drastically reduced memory usage and at least an order of magnitude speedup on our platform.

(The library in question was t1lib, a library originally released by Adobe, and the stupid memory handling is still in there as of today despite sporadic updates over the last decade; I guess it's not used much any more with FreeType, but I'm almost tempted to do a cleaner fix and submit it - the fix we did was not suitable for general usage as it explicitly assumed a single set of fonts would be loaded and unloaded in the same order, as it didn't keep pools per loaded font)



As someone with basic C experience, could you link me to some resources about how to use malloc properly (ie, allocating a block of RAM and managing it yourself)? I find the whole thing fascinating.


If you need both malloc and realloc, then these are not the droids you're looking for - the system implementation won't be that much slower than something you can hack together.

If you are using heap RAM for persistence over a long lived application, then again the system version is going to be helpful (you're going to allocate something like a 4KB chunk, and then you'll have to hang on to that as long as >= 1 byte is still needed from it, which will dramatically increase the RAM used by your process compared to what it requires.)

If your particular problem is just "I need to allocate some heap RAM because my arrays might be too big for the stack," then allocating one big chunk at the start of your function (of a size tailored to your particular problem) will save you a bunch of slow system calls.

Similarly, if your process is short lived, then you can also forget about free() calls, and just use one big buffer and your own allocator on it - see "everyone thinks about garbage collection the wrong way (2010)" http://blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047... (recent HN discussion: https://news.ycombinator.com/item?id=6131786 )




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: