My code does a lot of Input/Output and this often involves the creation of temporary arrays to hold bytes or chars of some size - i often use 4096. Im starting to wonder - without actual tests - to verify if it would be better to pool these arrays. My code would change to something like this
take array from pool
try {
read from one inputStream
write to another outputstream using array
} finally {
return array to pool
}
UPDATE I wrote a small program that did two things, created arrays and used an apache commons pool. Both looped a lot of times (100*100*100) and created/took, filled array, then released. I added a few goes in the beginning to warm up the jit and ignored the results of those. Each run ran the create and pool forms a dozen times, alternating between the two.
There was little difference between the pool and create forms. However if i added a clear array to the callback that is fired by apache commons pool when an instance is returned to a pool, the pool became that much slower thanthe created form.
I would not implement pooling until a performance problem was demonstrated.
Object pools add complexity to an application. In general, you have to deal with:
If you make a mistake in the pool implementation, you can introduce insidious bugs.
Is it worth it? Well, the answer depends on the circumstances:
If memory is severely constrained, GC pauses are a major issue, and/or the cost of allocating and initializing an object is large, then probably yes.
If the cost of "cleaning" and object is roughly the same as the amortized cost of allocating a new one, then it is doubtful.
To understand the last point, you need to understand some basic copying GC ergonomics. Specifically if you:
then the amortized GC cost of allocating and reclaiming memory for object in Java approaches the cost of zeroing memory.
Thus, if the cost of cleaning an object is roughly equivalent to the GC overhead (zeroing) + the object constructor cost, then the only thing you gain by pooling is reducing the number of times the GC marking / copying occurs. But you can do the same thing by simply giving the application a larger heap.
You could consider using the java.nio.Buffer
classes. For example, you could have something like this:
class ReadWorker {
private ByteBuffer buffer = ByteBuffer.allocate(4096);
public void work() {
fillBufferWithData();
buffer.flip();
doSomethingWithData();
buffer.clear();
}
}
Each call to work
will clear the buffer ready for the next call but you won't be allocating/deallocating memory all the time. flip
and clear
are very fast operations.
Having one Buffer
per worker will be easier than creating a pool with it's associated synchronisation fun-and-games.
EDIT: Note that I'm assuming you generate a fixed pool of workers so you're not creating new Buffer
objects all the time.
If you can't have a fixed worker pool then you could consider creating a pool of Buffer
objects rather than raw byte arrays. It depends on how you are using them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With