RE: Stack memory allocation


Subject: RE: Stack memory allocation
From: WJCarpenter (bill-abisource@carpenter.ORG)
Date: Thu Jul 13 2000 - 13:38:31 CDT


aaron> This patch reminded me off all the numerous places in the code
aaron> that just use char[4096] and limit the size of the string to
aaron> that long. These really gross me out but I'm afraid of a
aaron> performance penalty if I replace them with malloc() and the
aaron> right size. It just seems wrong to be wasteful with 4096k!!!
aaron> (I'm an assembly programmer too :)). Any ideas?

I haven't seen any of those, but I'm probably just nosing around
different parts of the code than you are. I agree they're gross, and
I've spent many a summer's eve wading through OPC (other people's
code) getting rid of stuff like this. I imagine this is old hat to
the veteran programmers on the list, but my guess is we have a range
of skill levels contributing, so please forgive the possible
tutorializing in the following comments.

It's always best if you can just somehow eliminate the fixed-size
buffers *and* avoid memory allocation, but there are plenty of legit
cases where you don't know the size of things until the function gets
called or until it computes what it needs or whatever. I believe in
the following techniques.

1. Given the choice between a fixed-size buffer and a memory
allocation penalty, choose the memory allocation penalty. That just
results in a performance problem, whereas the fixed-size buffer thing
often leads to the limitation of a feature, often silently, often
undocumented, sometimes with faulting behavior.

2. When doing memory allocation, use new/delete instead of
*alloc()/free(). Many environments will draw them from the same pool,
implementing one with a light wrapper around the other, but you can't
count on it. Memory allocation tends to lead to memory fragmentation,
which can lead to performance problems in many environments, and it's
better to have one fragmented memory heap than two. new/delete is the
more modern approach.

3. When performance matters (which includes all cases where you don't
know if performance matters :-), use a split approach that has
automatic storage for the common cases and uses memory allocation to
get around the limit of your fixed-size automatic storage buffer. The
pattern looks something like this (you could almost make it a macro):

        #define ASIZE 100 // size appropriate to the kinds of cases you see
        someType *p, a[ASIZE];
        if (qtyNeeded > ASIZE)
        {
                p = new someType[qtyNeeded];
        }
        else
        {
                p = a;
        }
        // ... some kind of processing
        if (p != a) delete p;

It usually takes only a few minutes to code up the above sort of fix
in existing code where you find either a fixed-size buffer or a memory
allocation.

-- 
bill@carpenter.ORG (WJCarpenter)    PGP 0x91865119
38 95 1B 69 C9 C6 3D 25    73 46 32 04 69 D6 ED F3



This archive was generated by hypermail 2b25 : Thu Jul 13 2000 - 13:41:14 CDT