In principle, I like this idea. It would make pools (and, consequently, APR) usable in a lot more programs.
In practice, there's at least one problem that I anticipate. In order to keep the pool implementation usable in the httpd, we can't slow down the fast-path code in apr_palloc() at all. I.e., the performance of the httpd depends very heavily on the fact that, when you use apr_palloc() to allocate from a pool that has enough free memory to satisfy the request without an additional block alloc, the path through the function is really damn fast. In the current code, the work required of apr_palloc() in the common case is basically just one integer comparison and a couple of addition operations. If we have to add even more more if-statement to the code to support ap_pfree(), then the run time of apr_palloc() will nearly double.
We saw this with the SMS allocators last year. SMS had a great design: a family of interchangeable allocators with different memory management implementations, and an single, abstract interface to all of them so that one could easily plug in the right type of allocator for a given app. The problem was that the httpd got measurably slower when the SMS version of the simple pool allocator was used in place of the original apr_pool code. The reason was that the single extra function call indirection on each apr_palloc() (to support the polymorphic interface) was enough to negatively impact the performance.
So...in order to be a general-purpose replacement for the current pool code, a pool implementation with apr_pfree() support would need to run also implement apr_palloc() without any performance penalty (at least for apps that don't need to take advantage of apr_pfree()). If your version of the pool code can handle that, though, then it might be a great addition to APR.
--Brian
Emery Berger wrote:
Hi everyone,
Not sure if this is the right place for this, but here goes.
I've recently developed an extended version of pools (called "reaps") that provides the same semantics but also allows individual objects to be freed and reused. That is, I add ap_pfree and ap_prealloc to the API. If you free an object with ap_pfree, it can be reused by a subsequent ap_palloc. If you don't ever use ap_pfree, it's still lightning fast and acts like the pools we all know and love :). If you do use ap_pfree, freed objects are managed using an algorithm based on Doug Lea's allocator, widely considered to be one of the most memory-efficient and fastest.
I see a couple of advantages to this approach:
(1) It should simplify module programming; existing code that uses malloc/free can just use ap_palloc(r->pool)/ap_pfree(r->pool) {say, by using a #define} and everything will work fine, rather than causing enormous memory consumption.
(2) Using reaps allows a broader range of memory usage patterns, e.g. producer-consumer pairs (producer allocs, consumer frees), which don't fit into the nested subpool paradigm.
So what are your thoughts? One notion I'm also working on is mixing reaps into Hoard, my scalable general-purpose memory allocator (see www.hoard.org). But I'm very interested in getting feedback on what the Apache crowd thinks about using reaps.
Thanks, -- Emery
-- Emery Berger Dept. of Computer Science The University of Texas at Austin www.cs.utexas.edu/users/emery
