Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add full set of RecyclerPool implementations #1064

Merged
merged 31 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c647bbf
Introducing BufferRecyclerPool
mariofusco Jul 19, 2023
b1eacd4
fix ReadConstrainedTextBufferTest to work with both a brand new Buffe…
mariofusco Jul 20, 2023
d5d3a14
minor refactor
mariofusco Jul 21, 2023
67459da
check performances of different object pool implementations
mariofusco Jul 24, 2023
7099315
ensure that all parsers and generators are properly closed in tests
mariofusco Jul 25, 2023
b404daf
cleanup pool implementations
mariofusco Jul 27, 2023
30dc6c3
make BufferRecycler closeable and disable the new ObjectPool by default
mariofusco Jul 27, 2023
0f8bd70
wip
mariofusco Jul 27, 2023
b09fd6e
wip
mariofusco Jul 27, 2023
d949043
javadoc + better pool management + pool decorator for debug
mariofusco Jul 28, 2023
b9c24c2
fix compilation problems after rebase
mariofusco Aug 22, 2023
44e446b
readd virtual threads friendly BufferRecyclerPool implementations
mariofusco Aug 22, 2023
835076c
add test class
mariofusco Aug 22, 2023
843648b
...
cowtowncoder Aug 27, 2023
98691fc
Fix a merge issue
cowtowncoder Aug 27, 2023
5cf738d
...
cowtowncoder Aug 27, 2023
2e64334
wip
mariofusco Aug 28, 2023
3375a0b
fix tests
mariofusco Aug 28, 2023
643e5e6
add comments
mariofusco Aug 28, 2023
454018c
remove enum of pool implementations
mariofusco Aug 28, 2023
1d01060
Merge branch '2.16' into 216_buffer_recycler_pool
cowtowncoder Aug 30, 2023
5594136
Minor tweaks: add javadoc, reduce diff from 2.16
cowtowncoder Aug 30, 2023
e3a0971
Bit more cleanup; remove addition of default recycler pool access via…
cowtowncoder Aug 30, 2023
16add03
Warnings removal
cowtowncoder Aug 30, 2023
d9e585b
Merge branch '2.16' into 216_buffer_recycler_pool
cowtowncoder Aug 30, 2023
79b2885
Refactoring, adding more Javadocs
cowtowncoder Aug 30, 2023
0f359fc
Minor change to test class
cowtowncoder Aug 30, 2023
5394156
improve tests checking that pooled BufferRecycler is properly acquire…
mariofusco Aug 30, 2023
9d53f00
add bounded pool implementation
mariofusco Aug 30, 2023
58e6f30
Adding Javadocs, minor renaming
cowtowncoder Aug 30, 2023
eb2461b
Implement sharing-retaining JDK serialization for BufferRecyclerPools.
cowtowncoder Aug 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.io.Serializable;
import java.util.Deque;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicReference;

Expand All @@ -22,23 +24,23 @@ public interface BufferRecyclerPool extends Serializable
* which is the thread local based one:
* basically alias to {@link #threadLocalPool()}).
*/
public static BufferRecyclerPool defaultPool() {
static BufferRecyclerPool defaultPool() {
return threadLocalPool();
}

/**
* @return Shared instance of {@link ThreadLocalPool}; same as calling
* {@link ThreadLocalPool#shared()}.
*/
public static BufferRecyclerPool threadLocalPool() {
static BufferRecyclerPool threadLocalPool() {
return ThreadLocalPool.shared();
}
pjfanning marked this conversation as resolved.
Show resolved Hide resolved

/**
* @return Shared instance of {@link NonRecyclingPool}; same as calling
* {@link NonRecyclingPool#shared()}.
*/
public static BufferRecyclerPool nonRecyclingPool() {
static BufferRecyclerPool nonRecyclingPool() {
return NonRecyclingPool.shared();
}

Expand All @@ -53,7 +55,7 @@ public static BufferRecyclerPool nonRecyclingPool() {
* Android), or on platforms where {@link java.lang.Thread}s are not
* long-living or reused (like Project Loom).
*/
public static class ThreadLocalPool implements BufferRecyclerPool
class ThreadLocalPool implements BufferRecyclerPool
{
private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -89,7 +91,7 @@ public void releaseBufferRecycler(BufferRecycler recycler) {
* {@link BufferRecyclerPool} implementation that does not use
* any pool but simply creates new instances when necessary.
*/
public static class NonRecyclingPool implements BufferRecyclerPool
class NonRecyclingPool implements BufferRecyclerPool
{
private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -126,7 +128,7 @@ public void releaseBufferRecycler(BufferRecycler recycler) {
* {@link BufferRecyclerPool} implementation that uses
* {@link ConcurrentLinkedDeque} for recycling instances.
*/
public static class ConcurrentDequePool implements BufferRecyclerPool
class ConcurrentDequePool implements BufferRecyclerPool
{
private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -192,7 +194,7 @@ public void releaseBufferRecycler(BufferRecycler bufferRecycler) {
* {@link BufferRecyclerPool} implementation that uses
* a lock free linked list for recycling instances.
*/
public static class LockFreePool implements BufferRecyclerPool
class LockFreePool implements BufferRecyclerPool
{
private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -285,4 +287,70 @@ static class Node {
}
}
}

/**
* {@link BufferRecyclerPool} implementation that uses
* a bounded queue for recycling instances.
*/
class BoundedPool implements BufferRecyclerPool
{
private static final long serialVersionUID = 1L;

private static final BufferRecyclerPool SHARED = new BoundedPool(16);
cowtowncoder marked this conversation as resolved.
Show resolved Hide resolved

private final transient Queue<BufferRecycler> pool;

// // // Life-cycle (constructors, factory methods)

protected BoundedPool(int capacity) {
pool = new ArrayBlockingQueue<>(capacity);
}

/**
* Accessor for getting the globally shared singleton instance.
* Note that if you choose to use this instance,
* pool may be shared by many other {@code JsonFactory} instances.
*
* @return Shared pool instance
*/
public static BufferRecyclerPool shared() {
return SHARED;
}

/**
* Accessor for creating and returning a new, non-shared pool instance.
*
* @return Newly constructed, non-shared pool instance
*/
public static BufferRecyclerPool nonShared(int capacity) {
return new BoundedPool(capacity);
}

// // // JDK serialization support

/**
* To avoid serializing pool contents we made {@code pool} {@code transient};
* to compensate, need to re-create proper instance using constructor.
*/
protected Object readResolve() {
return SHARED;
}

// // // Actual API implementation

@Override
public BufferRecycler acquireBufferRecycler() {
return getBufferRecycler().withPool(this);
}

private BufferRecycler getBufferRecycler() {
BufferRecycler bufferRecycler = pool.poll();
return bufferRecycler != null ? bufferRecycler : new BufferRecycler();
}

@Override
public void releaseBufferRecycler(BufferRecycler bufferRecycler) {
pool.offer(bufferRecycler);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,23 @@ public void testThreadLocal() {
}

public void testLockFree() {
checkBufferRecyclerPoolImpl(BufferRecyclerPool.LockFreePool.shared(), true);
checkBufferRecyclerPoolImpl(BufferRecyclerPool.LockFreePool.nonShared(), true);
}

public void testConcurrentDequeue() {
checkBufferRecyclerPoolImpl(BufferRecyclerPool.ConcurrentDequePool.shared(), true);
checkBufferRecyclerPoolImpl(BufferRecyclerPool.ConcurrentDequePool.nonShared(), true);
}

public void testBounded() {
checkBufferRecyclerPoolImpl(BufferRecyclerPool.BoundedPool.nonShared(1), true);
}

private void checkBufferRecyclerPoolImpl(BufferRecyclerPool pool, boolean checkPooledResource) {
JsonFactory jsonFactory = JsonFactory.builder()
.bufferRecyclerPool(pool)
.build();
BufferRecycler usedBufferRecycler = write("test", jsonFactory, 6);

if (checkPooledResource) {
// acquire the pooled BufferRecycler again and check if it is the same instance used before
BufferRecycler pooledBufferRecycler = pool.acquireBufferRecycler();
Expand Down