Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm implementing a system in C, implemented partially as a library. The library does most of the memory management itself, with the application layer just having to call *_destroy functions on the top-level objects.

While checking for memory leaks, I noticed that the number of calls to malloc seemed quite high, relative to the size of the application code. The performance of the code seems fine, but I've been bitten by "fast enough" code before when trying to scale.

The number of allocations roughly matches the number of objects created, including child objects of the top-level ones. So creating a single top-level object might trigger 7 malloc calls, since it needs one for itself and then a couple for it's children that may also need a few children.

Unfortunately, I'm relatively new to C programming, though generally experienced as a programmer, and have no idea whether or these numbers are normal or not.

So what would a good rule-of-thumb be for number of allocations? I know that less would generally be better, but changing the code to allow it would introduce complexity that I'm not willing to add without a significant increase in performance.

Also, should I worry about the performance of malloc/free or is that the realm of real-time performance (games etc.)?

share|improve this question
add comment

2 Answers 2

up vote 1 down vote accepted

The usual answer for this thing is to wait until you can measure if there's a problem.

My experience has been that malloc() is rarely an issue, but perhaps I also do more CPU-intensive work than you do, so malloc() isn't in the critical path.

Definitely some people are constrained by the malloc performance. See, for example, https://github.com/blog/1422-tcmalloc-and-mysql , where github switched to using TCMalloc for MySQL and got a 30% performance improvement. There's more discussion at http://www.reddit.com/r/programming/comments/18zija/github_got_30_better_performance_using_tcmalloc/ .

TCMalloc is one of several malloc replacements. Another is jemalloc, and a third is nedmalloc.

So, if you think it's a problem (eg, because profiling shows that you're stuck in malloc/free often) then try one of those out and see if it improves things.

If it's a concern now, then perhaps you can think about how your code is structured. The biggest improvement is to realize that you don't need to think of "one structure = one malloc."

For example, I once wrote a parser for a tab-separated document. While I could have turned each row and field into its own string, it was faster to scan the document, count the number of rows and columns, and do a single malloc for the row/field pointers. Then in the second step, scan the document again, assign the correct pointers to the head of each field, and replace the tabs and newlines with a NUL to get proper NUL-terminated strings for the field.

This meant that my parser now "owned" the document string, which was acceptable. And it reduced the complexity of the code, even if the malloc performance wasn't critical.

share|improve this answer
    
It's not actually a problem right now, I just don't want it to become a problem. The 1-malloc-per-object is more down to the way the api is designed than a specific though process. I have written code (a parser too) that worked like your parser. –  Aatch Mar 20 '13 at 0:57
add comment

It's not always the malloc and free performance that is an issue. You can run into problems with cache locality (or rather a lack of cache locality), and that can really hit performance if you are doing a lot of processing on the data.

If you are worried you could switch to a memory-pooled scheme for all, most, or some parts of your API. I'm sure there are plenty of tools out there to do this in a generic way, but more often than not the pooling requirements of an application are so basic that it's trivial to implement yourself.

Unfortunately, you are the best judge of whether pooling will benefit your application, and whether it is worth the effort and increased complexity. Just remember, a pool can be as simple as a large char buffer.

Just watch out for memory alignment issues (like don't start objects at non-aligned memory addresses).

A classic argument I like to give for memory pools is a 2D array...

So often, you see people allocate a chunk for the row pointers, and then loop through allocating each row... You have to do more error handling, the 'delete' function is a pain, and at the end of it you get a matrix whose row index and individual rows could be fragmented across your address space.

Yet, all you really needed to do was allocate one block of memory with enough space for a bunch of pointers and the 2D data segment, then index it. It's not technically a pool, but it is smarter use of memory.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.