Skip to content

Instantly share code, notes, and snippets.

@tom-smalls
Last active June 29, 2016 13:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tom-smalls/fe73f771d9950d65789004e75b87ee4c to your computer and use it in GitHub Desktop.
Save tom-smalls/fe73f771d9950d65789004e75b87ee4c to your computer and use it in GitHub Desktop.
Several object pool implementations to test allocation and ops/s
public interface ObjectPool
{
ObjectPool NOT_POOLED = new NotObjectPooled();
T get();
void returnObject(T instance);
interface ObjectFactory
{
T create();
}
}
@State(Scope.Thread)
public class QueueObjectPoolUsingDequeBenchmark
{
private static final MutableString INSTANCE = new MutableString(1024);
private volatile int counter;
private ObjectPool objectPool;
@Setup
public void setup()
{
objectPool = new QueueBasedObjectPool<>(() -> INSTANCE);
}
@Benchmark
public int removeAndAddOne() throws Exception
{
final MutableString mutableString = objectPool.get();
counter += mutableString.getLength();
objectPool.returnObject(mutableString);
return counter;
}
@Benchmark
public int removeAndAddSeveral() throws Exception
{
final MutableString mutableString1 = objectPool.get();
counter += mutableString1.getLength();
final MutableString mutableString2 = objectPool.get();
counter += mutableString2.getLength();
final MutableString mutableString3 = objectPool.get();
counter += mutableString3.getLength();
objectPool.returnObject(mutableString3);
objectPool.returnObject(mutableString2);
objectPool.returnObject(mutableString1);
return counter;
}
private static final class QueueBasedObjectPool implements ObjectPool
{
private static final int NUM_ELEMENTS = 20;
private final Queue instances = new ArrayDeque<>(NUM_ELEMENTS);
private final ObjectFactory objectFactory;
public QueueBasedObjectPool(final ObjectFactory objectFactory)
{
this.objectFactory = objectFactory;
prePopulate();
}
@Override
public T get()
{
final T instance = instances.poll();
if (instance == null)
{
return objectFactory.create();
}
return instance;
}
private void prePopulate()
{
for (int i = 0; i < NUM_ELEMENTS; i++)
{
returnObject(objectFactory.create());
}
}
@Override
public void returnObject(final T instance)
{
instances.add(instance);
}
}
}
public class StackObjectPoolBenchmark
{
private static final MutableString INSTANCE = new MutableString(1024);
private volatile int counter;
private ObjectPool objectPool;
@Setup
public void setup(final Blackhole bh)
{
objectPool = new StackBasedObjectPool<>(() -> INSTANCE);
}
@Benchmark
public int removeAndAddOne() throws Exception
{
final MutableString mutableString = objectPool.get();
counter += mutableString.getLength();
objectPool.returnObject(mutableString);
return counter;
}
@Benchmark
public int removeAndAddSeveral() throws Exception
{
final MutableString mutableString1 = objectPool.get();
counter += mutableString1.getLength();
final MutableString mutableString2 = objectPool.get();
counter += mutableString2.getLength();
final MutableString mutableString3 = objectPool.get();
counter += mutableString3.getLength();
objectPool.returnObject(mutableString3);
objectPool.returnObject(mutableString2);
objectPool.returnObject(mutableString1);
return counter;
}
private static final class StackBasedObjectPool implements ObjectPool
{
private static final int NUM_ELEMENTS = 20;
private final Stack instances = new Stack<>();
private final ObjectFactory objectFactory;
public StackBasedObjectPool(final ObjectFactory objectFactory)
{
this.objectFactory = objectFactory;
prePopulate();
}
@Override
public T get()
{
if (instances.peek() == null)
{
return objectFactory.create();
}
return instances.pop();
}
private void prePopulate()
{
for (int i = 0; i < NUM_ELEMENTS; i++)
{
returnObject(objectFactory.create());
}
}
@Override
public void returnObject(final T instance)
{
instances.push(instance);
}
}
}
@State(Scope.Thread)
public class StackObjectPoolUsingArrayBenchmark
{
private static final MutableString INSTANCE = new MutableString(1024);
private volatile int counter;
private ObjectPool objectPool;
@Setup
public void setup(final Blackhole bh)
{
objectPool = new ArrayObjectPool<>(() -> INSTANCE);
}
@Benchmark
public int removeAndAddOne() throws Exception
{
final MutableString mutableString = objectPool.get();
counter += mutableString.getLength();
objectPool.returnObject(mutableString);
return counter;
}
@Benchmark
public int removeAndAddSeveral() throws Exception
{
final MutableString mutableString1 = objectPool.get();
counter += mutableString1.getLength();
final MutableString mutableString2 = objectPool.get();
counter += mutableString2.getLength();
final MutableString mutableString3 = objectPool.get();
counter += mutableString3.getLength();
objectPool.returnObject(mutableString3);
objectPool.returnObject(mutableString2);
objectPool.returnObject(mutableString1);
return counter;
}
private static final class ArrayObjectPool implements ObjectPool
{
private static final int NUM_ELEMENTS = 16;
private Object[] instances = new Object[NUM_ELEMENTS << 1];
private int pointer = -1;
private final ObjectFactory objectFactory;
public ArrayObjectPool(final ObjectFactory objectFactory)
{
this.objectFactory = objectFactory;
populate(0, NUM_ELEMENTS);
}
@SuppressWarnings("unchecked")
@Override
public T get()
{
++pointer;
if (pointer == instances.length)
{
final int oldLength = instances.length;
final int newLength = oldLength << 1;
if (newLength < 0)
{
throw new IllegalStateException("Queue too big");
}
instances = new Object[newLength];
}
if (instances[pointer] == null)
{
return objectFactory.create();
}
final T instance = (T)instances[pointer];
instances[pointer] = null;
return instance;
}
@Override
public void returnObject(final T instance)
{
instances[pointer--] = instance;
}
private void populate(final int start, final int amount)
{
for (int i = start; i < amount + start; i++)
{
instances[i] = objectFactory.create();
}
}
}
}
@State(Scope.Thread)
public class StackObjectPoolUsingDequeBenchmark
{
private static final MutableString INSTANCE = new MutableString(1024);
private volatile int counter;
private ObjectPool objectPool;
@Setup
public void setup(final Blackhole bh)
{
objectPool = new StackUsingDequeObjectPool<>(() -> INSTANCE);
}
@Benchmark
public int removeAndAddOne() throws Exception
{
final MutableString mutableString = objectPool.get();
counter += mutableString.getLength();
objectPool.returnObject(mutableString);
return counter;
}
@Benchmark
public int removeAndAddSeveral() throws Exception
{
final MutableString mutableString1 = objectPool.get();
counter += mutableString1.getLength();
final MutableString mutableString2 = objectPool.get();
counter += mutableString2.getLength();
final MutableString mutableString3 = objectPool.get();
counter += mutableString3.getLength();
objectPool.returnObject(mutableString3);
objectPool.returnObject(mutableString2);
objectPool.returnObject(mutableString1);
return counter;
}
private static final class StackUsingDequeObjectPool implements ObjectPool
{
private static final int NUM_ELEMENTS = 20;
private final Deque instances = new ArrayDeque<>(NUM_ELEMENTS);
private final ObjectFactory objectFactory;
public StackUsingDequeObjectPool(final ObjectFactory objectFactory)
{
this.objectFactory = objectFactory;
prePopulate();
}
@Override
public T get()
{
final T instance = instances.poll();
if (instance == null)
{
return objectFactory.create();
}
return instance;
}
private void prePopulate()
{
for (int i = 0; i < NUM_ELEMENTS; i++)
{
returnObject(objectFactory.create());
}
}
@Override
public void returnObject(final T instance)
{
instances.addFirst(instance);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment