httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@arctic.org>
Subject Re: memory allocation (was Re: Why bother with APR?)
Date Tue, 21 Sep 1999 09:07:25 GMT
On Tue, 21 Sep 1999, Manoj Kasichainula wrote:

> On Tue, Sep 14, 1999 at 09:43:27AM -0700, Dean Gaudet wrote:
> > note:  when i was suggesting adding cleanups for malloc'd memory i really
> > wasn't suggesting that a cleanup be added for each piece of malloc'd
> > memory.  that will consume a fair bit more memory per allocation... i was
> > actually thinking the solution would be to prefix the malloc allocation
> > with a struct mem { mem *next; mem *prev }; ... and having a single
> > cleanup which walks the entire list of malloc allocations.
> 
> Sounds like a pool to me. :) What's the advantage of this? If the list
> is short, we're reverting closer to the one-malloc-per-cleanup case.
> If the list is long, pools start looking really good. Or am I missing
> something?

it'd be cool if we could stop calling the memory allocator a pool, it
confuses things... a pool is just a place to hang cleanups in my opinion
(which gets us back to the "why create contexts" debate, because contexts
appear to just be pools with an extra void *, but i digress).

i'm not sure what piece you're missing... but here's the main points:

- we're debating on adding an ap_malloc() and a companion ap_free() --
  malloc returns something which lives until a free or the pool is
  cleared, whichever comes first.  we want this for various reasons i've
  already mentioned (shared caches being the main case).

- cleanups are a singly linked list.  if you have a cleanup for each
  malloced bit of ram, then you get wonderful O(n^2) behaviours depending
  on the free() patterns.

- if you make cleanups a doubly-linked list then you're still stuck with
  O(n^2) behaviour for free because you still need to find which
  cleanup is associated with the piece of memory.

- or you could adjust the malloc size by sizeof(void *) and stick a
  back pointer to the cleanup in it... but if you're going to do this,
  you might as well adjust the malloc size by sizeof(struct mem)
  where struct mem { mem *next; mem *prev };.  this way free() is
  O(1).

- this last case also has the advantage that an ap_malloc() only
  requires one call to malloc(), not two (one for the result, one
  for the cleanup).

Or, another alternative:

- don't use malloc/free to implement ap_malloc/ap_free.  instead grab
  some malloc implementation (such as *bsd's) and modify it to
  use ap_palloc underneath instead of going through brk()/sbrk().

- this way you don't need any cleanups for the ap_malloc -- you assume
  that the caller will always call ap_free() with the right pool.

Or, another alternative:

- ap_malloc and ap_free are not associated with pools at all, the users
  of them have to do their own resource management.  this is exactly
  the route i've taken already if you look around at the few malloc()s
  i put in.

Dean


Mime
View raw message