You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Ioan Popescu <ip...@dataq.com> on 2006/11/01 17:12:08 UTC

APR Pools

Are "pools" here to stay? Or are there plans to abandon them, use them less?

If they're here to stay, could someone tell me what advantages there are to
using them instead of malloc()/free()? Regardless of portability.

I've read about a number of new "problems" (Subversion has come up with some
solutions) specific to the use of pools. Not to mention the potential for
"internal memory leaks" as a result of unbounded operations.

Also, a bit of a headache to force onto a client: use pools, or provide an
abstraction API. This is a big problem when you don't know the lifetime of
objects and likely end up using some common pool for them with a very long
lifetime. Any solutions for this?

I've read http://www.apachetutor.org/dev/pools for some help, but it's still
a vague concept for me.

---
Ioan


Re: APR Pools

Posted by Bojan Smojver <bo...@rexursive.com>.
Quoting Bojan Smojver <bo...@rexursive.com>:

> Apache has a notion of maximum number of requests a child process will
> handle. This can help with memory leaks, as processes simply get
> recycled after a while, therefore freeing any "long lifetime" memory
> that may have leaked in the child during its service period. Not
> suitable for all apps, but may help in some situations.

What I mean here is that you can sometimes design your app similar to  
the way Apache is designed, with the lead process and workers which  
then get recycled.

-- 
Bojan

Re: APR Pools

Posted by Ioan Popescu <ip...@dataq.com>.
Bojan Smojver wrote:
> - faster than many malloc() implementations, especially on pool reuse
> 
> - can attach generic cleanup functions to them, with same lifetime
> 
> - one cleanup does it all, instead of many free()'s

Please tell me if my understanding of pools is wrong/right. A chunk of
system memory is allocated. Requests for memory are "allocated" from this
already allocated memory. What about fragmentation algorithms/problems? Yes,
I know the system also has to worry about this. Never mind. It just occurred
to me that nothing allocated is ever deallocated until the pool is
cleared/destroyed.

> - can have subpools for allocating memory in a branch of code that may 
> end up in an error, in which case the subpool can be easily dumped 
> without affecting the parent pool, therefore reducing the memory pressure

I like this.

> Apache has a notion of maximum number of requests a child process will 
> handle. This can help with memory leaks, as processes simply get recycled
> after a while, therefore freeing any "long lifetime" memory that may have
> leaked in the child during its service period. Not suitable for all apps,
> but may help in some situations.

Sounds like a good idea, but I'm developing a library. It can't just release
old memory because that might crash an application. Unless I "own" the
memory (or claim I do), I can't just release it.

Graham Leggett wrote:
> In both cases, the library user has to call some kind of cleanup function
>  to return the memory back to the library. Whether that cleanup function 
> calls "free" for all allocated blocks, or "apr_pool_destroy", it amounts 
> to the same responsiblity from the caller.
> 
> If a particular function in your library "do_stuff" has to do stuff 
> without requiring a cleanup afterwards, create a subpool at the start of 
> do_stuff, and destroy it at the end before return.

True, but I thought one was supposed to avoid per object pools? If I create
a pool for every type of object, doesn't that just make it unbounded? I
would have to implement reference counting to decide when to clear the pool.
Well, since the objects requiring reference counting aren't on the critical
path, I could implement it.

Maybe my packet processing library has some similarities to Apache. I listen
for packets, I parse the raw packets into structures allocated from a packet
pool. I run these processed packets through client provided
filters/operations. I'm finished with the packet. Sounds easy enough. How do
I "free" the packet? Just clear the pool before processing the next packet?
Unless other complications arise (working on multithreading), this sounds
like it should work for this scenario (I also have other objects that
dictate logic prior to this packet processing).

Re: APR Pools

Posted by Bojan Smojver <bo...@rexursive.com>.
Quoting Ioan Popescu <ip...@dataq.com>:

> If they're here to stay, could someone tell me what advantages there are to
> using them instead of malloc()/free()? Regardless of portability.

- well suited for request/response situations (i.e. limited object lifetime)

- faster than many malloc() implementations, especially on pool reuse

- can attach generic cleanup functions to them, with same lifetime

- one cleanup does it all, instead of many free()'s

- can have subpools for allocating memory in a branch of code that may  
end up in an error, in which case the subpool can be easily dumped  
without affecting the parent pool, therefore reducing the memory  
pressure

> This is a big problem when you don't know the lifetime of
objects and likely end up using some common pool for them with a very long
lifetime. Any solutions for this?

Apache has a notion of maximum number of requests a child process will  
handle. This can help with memory leaks, as processes simply get  
recycled after a while, therefore freeing any "long lifetime" memory  
that may have leaked in the child during its service period. Not  
suitable for all apps, but may help in some situations.

-- 
Bojan

Re: APR Pools

Posted by Graham Leggett <mi...@sharp.fm>.
On Wed, November 1, 2006 6:12 pm, Ioan Popescu wrote:

> If they're here to stay, could someone tell me what advantages there are
> to
> using them instead of malloc()/free()? Regardless of portability.

In typical code, there are many possible paths, including possible failure
paths to account for. Once your code is done, you need to free memory
you've malloc'ed. Add a few more esoteric code paths, like handling
abort-on-timeout, and it gets even more complex. Did we free all the
memory we malloc'ed?

Sometimes it can be just plain difficult to keep track of your own memory
usage. When your code ends, you want a way to say "just clean up, dammnit"
and be done with it.

Pools give you this.

Right at the beginning, you define a pool. You attempt your task,
following one of many possible code paths, allocating RAM as and when you
need it. Maybe your task succeeds, maybe it fails with an error, doesn't
matter - right at the end of the task, you destroy your pool, and you have
peace of mind that all the memory you allocated is gone.

Of course, this isn't a solution for every problem. If your task involves
the allocating of excessive RAM, you effectively have a leak inside your
task. You might want to delete something just malloc'ed right away, and
not wait right till the end of the task.

One solution to this is create a subpool off a main pool. Subpools are
independent pools that can be created and destroyed at will, but they have
the property of being destroyed when the pool the subpool was created from
gets destroyed. Create the subpool, allocate the memory, destroy the
subpool, carry on going. Some argue that the above solution, while it
works, isn't that efficient, and it may not be efficient enough for your
application.

Regards,
Graham
--