On Mon, Jun 10, 2002 at 11:46:46AM +0300, Zeev Suraski wrote:
> What we need for efficient thread-safe operation is a mechanism like the 
> Win32 heaps - mutexless heaps, that provide malloc and free services on a 
> (preferably) contiguous pre-allocated block of memory.  The question is 
> whether the APR allocators fall into that category:
> 
> 1.  Can you make them mutexless completely?  I.e., will they never call 
> malloc()?

APR's pools only use malloc() as a portable way to retrieve large
chunks of heapspace that are never returned. I don't know of any
other portable way to do this.

In any case, at some level you will always have a mutex. Either you
are mapping new segments in to the memory space of the process, or
you are dealing with freelists in userspace. APR pools take the
approach that by doing more up-front segment mapping and delayed
freeing of chunks, we avoid many of the mutexes and overhead of
freelist management. It's still got to happen somewhere though.

> 2.  They definitely do provide alloc/free services, we're ok there

Pretty much, but it's not exactly the same. I'll outline some thoughts
on a potential memory allocation abstraction that could be implemented
w/ apr_pools or Win32 heaps below...

> 3.  As far as I can tell, they don't use a contiguous block of memory, 
> which means more fragmentation...

I'm not sure how contiguity relates to fragmentation. With a pool
you can do mallocs all day long, slowly accumulating more 8K blocks
(which may or may not be contiguous). At the end of the pool lifetime
(let's say, for example, at the end of a request) then those blocks
are placed on a freelist, and the sub-partitions within those blocks
are simply forgotten. On the next request, the process starts over again.


I think to properly abstract a memory allocation scheme that can be
implemented in a way that is optimized for the particular SAPI module,
we'll have to abstract out a few concepts. This list is not exhaustive,
but is just a quick sketch based on my understanding of Win32 heaps
and APR pools:

   - creation (called once per server lifetime)
   - malloc (called many times per request)
   - free (called many times per request)
   - end-of-request (called many times per request)
   - destruction (called once per serve lifetime)

Does this cover all our bases? For example, when using pools, the
free() call would do nothing, and the end-of-request call would simply
call apr_pool_clear(). Note that this only applies to dynamically
allocated memory required for the lifetime of a request. For memory
with longer lifetimes we could make the creation and destruction
routines more generic.

-aaron

Reply via email to