views:

126

answers:

6

Going through the Goetz "Java Concurrency in Practice" book, he makes a case against using object pooling (section 11.4.7) - main arguments:

1) allocation in Java is faster than C's malloc 2) threads requesting objects from a pool require costly synchronization

My problem is not so much that allocation is slow, but that periodic garbage collection introduces outliers in response time that could be eliminated by reducing object pools.

Are there any issues that I am not seeing in using this approach? Essentially I am partitioning an object pool across the threads...

+2  A: 

If its thread local then you can forget about this:

2) threads requesting objects from a pool require costly synchronization

Being thread-local you need not worry about synchronization to retrieve from the pool itself.

John V.
Doesn't the "Concurrency" part of the book title suggest that it is about multi-threading?
luiscubal
Who says hes not multi-threading? What if each thread pool has its own Thread specific set of data that is irrelevant to other threads?
John V.
@luiscubal: thread-local doesn't mean non-multi-threading; it means a pool for each thread. since it's private to the thread, it doesn't need to synchronize with other threads to pick an object form it's own pool.
Javier
@Javier @John V: If it is thread-local then it can be thread-unsafe, so I'm guessing there'd be little need for concurrent-specific algorithms(as common old programming is just fine), so I don't see how the book reference would even be relevant.
luiscubal
@luiscubal can you explain how a thread-local object is thread-unsafe?
John V.
@John V. The effort of making something thread-local thread-safe is, the way I see it, useless. Then again, maybe the correct wording for this case is that thread-local is automatically thread-safe.
luiscubal
@luiscubal Thatch exactly it, you wouldn't make something thread-local thread safe because its inherently thread-safe. But making the pool thread-local isn't useless in this case. The synchronization is also for memory visibility. If there are definitely threads changing the objects in the pool, then a synchronization point needs to be in place to ensure all threads see up-to-date values. I guess my point is, if its thread-local he does not need to worry about goetz's second point
John V.
A: 

I think your case is reasonable situation to use pooling. There is no evil in pooling, Goetz means that you should not use it when it is not necessary. Another example is connection pooling, because creation of connection is very expensive.

Andrey
There are many evils in pooling.
Tom Hawtin - tackline
A: 

In Java 1.4, object allocation was relatively expensive so Object pools for even simple objects could help. However, in Java 5.0, Object allocation was significantly improved, however synchronization still had a way to go meaning that object allocation was faster than synchronization. i.e. removing object pools improved performance in many cases. In Java 6, synchronization has improved to the point where an object pool can make little difference to performance in simple cases. Avoiding simple object pools is a good idea because it is simpler, not for performance reasons.

For more complex/larger objects, object pools can be useful in Java 6, even if you use synchronization.

Peter Lawrey
A: 

(sun's) GC scans live objects. the assumption is that there are way more dead objects than live objects in a typical java program runtime. it marks live objects, and dispose the rest.

if you cache a lot of objects, they are all live. and if you have several GBs of such objects, GC is going to waste a lot of time scanning them in vain. long GC pauses can paralyze your application.

cache something just to make it non-garbage is not helping GC.

that's not to say caching is wrong. if you have 15G memory, and your database is 10G, why not cache everything in memory, so responses are lighting fast. note this is to cache something that would otherwise be slow to fetch.

to prevent GC from fruitlessly scanning the 10G cache, the cache must be outside GC's control. For example, use 'memcached" which lives in another process, and has its own cache-optimized GC.

the latest news is Terracotta's BigMemory which is a pure java solution that does similar thing.


an example of thread local pooling is sun's direct ByteBuffer pooling. when we call

channel.read(byteBuffer)

if byteBuffer is not "direct", a "direct" one must be allocated under the hood, used to communicate data with OS. in a network application, such allocations could be very frequent, it seems to be a waste, to discard a just allocated one, and immediately allocate another one in the next statement. sun's engineers, apparently don't trust GC that much, created a thread local pool of "direct" ByteBuffers.

irreputable
A: 

If it is threadlocal, it's very likely you may not even need pooling. Of course it would depend on the use cases, but the chances are, on a given thread you will likely need only one object of that type at a given time.

The caveat with threadlocals, however, is memory management. Note that threadlocal values don't go away easily until the thread that owns those threadlocals go away. Therefore, if you have a large number of threads and a large number of threadlocals, they may contribute to used memory quite a bit.

sjlee