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 all commits
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
24 changes: 13 additions & 11 deletions src/main/java/com/fasterxml/jackson/core/JsonFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,7 @@
import com.fasterxml.jackson.core.json.async.NonBlockingJsonParser;
import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer;
import com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer;
import com.fasterxml.jackson.core.util.BufferRecycler;
import com.fasterxml.jackson.core.util.BufferRecyclerPool;
import com.fasterxml.jackson.core.util.BufferRecyclers;
import com.fasterxml.jackson.core.util.JacksonFeature;
import com.fasterxml.jackson.core.util.JsonGeneratorDecorator;
import com.fasterxml.jackson.core.util.Separators;
import com.fasterxml.jackson.core.util.*;

/**
* The main factory class of Jackson package, used to configure and
Expand Down Expand Up @@ -115,8 +110,10 @@ public enum Feature
FAIL_ON_SYMBOL_HASH_OVERFLOW(true),

/**
* Feature that determines whether we will use {@link BufferRecycler} with
* {@link ThreadLocal} and {@link SoftReference}, for efficient reuse of
* Feature that determines whether we will use a {@link BufferRecyclerPool}
* for allocating and possibly recycling {@link BufferRecycler} or not.
* The default {@link BufferRecyclerPool} implementation uses
* {@link ThreadLocal} and {@link SoftReference} for efficient reuse of
* underlying input/output buffers.
* This usually makes sense on normal J2SE/J2EE server-side processing;
* but may not make sense on platforms where {@link SoftReference} handling
Expand All @@ -125,6 +122,10 @@ public enum Feature
* <a href="https://github.com/FasterXML/jackson-core/issues/189">jackson-core#189</a>
* for a possible case)
*<p>
* Note that since 2.16 naming here is somewhat misleading as this is used
* to now enable or disable pooling; but the actual pooling implementation
* is configurable and may not be based on {@link ThreadLocal}.
*<p>
* This setting is enabled by default.
*
* @since 2.6
Expand Down Expand Up @@ -370,7 +371,7 @@ public static int collectDefaults() {
public JsonFactory() { this((ObjectCodec) null); }

public JsonFactory(ObjectCodec oc) {
_bufferRecyclerPool = BufferRecyclers.defaultRecyclerPool();
_bufferRecyclerPool = BufferRecyclerPool.defaultPool();
_objectCodec = oc;
_quoteChar = DEFAULT_QUOTE_CHAR;
_streamReadConstraints = StreamReadConstraints.defaults();
Expand Down Expand Up @@ -1873,6 +1874,7 @@ protected JsonParser _createParser(InputStream in, IOContext ctxt) throws IOExce
e.addSuppressed(e2);
}
}
ctxt.close();
cowtowncoder marked this conversation as resolved.
Show resolved Hide resolved
throw e;
}
}
Expand Down Expand Up @@ -2151,7 +2153,7 @@ protected JsonGenerator _decorate(JsonGenerator g) {
*/
public BufferRecycler _getBufferRecycler()
cowtowncoder marked this conversation as resolved.
Show resolved Hide resolved
{
return _getBufferRecyclerPool().acquireBufferRecycler(this);
return _getBufferRecyclerPool().acquireBufferRecycler();
}

/**
Expand All @@ -2165,7 +2167,7 @@ public BufferRecyclerPool _getBufferRecyclerPool() {
// scheme, for cases where it is considered harmful (possibly
// on Android, for example)
if (!Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING.enabledIn(_factoryFeatures)) {
return BufferRecyclers.nopRecyclerPool();
return BufferRecyclerPool.nonRecyclingPool();
}
return _bufferRecyclerPool;
}
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/com/fasterxml/jackson/core/TSFBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.json.JsonWriteFeature;
import com.fasterxml.jackson.core.util.BufferRecyclerPool;
import com.fasterxml.jackson.core.util.BufferRecyclers;
import com.fasterxml.jackson.core.util.JsonGeneratorDecorator;

/**
Expand Down Expand Up @@ -142,7 +141,7 @@ protected TSFBuilder(JsonFactory base)
protected TSFBuilder(int factoryFeatures,
int parserFeatures, int generatorFeatures)
{
_bufferRecyclerPool = BufferRecyclers.defaultRecyclerPool();
_bufferRecyclerPool = BufferRecyclerPool.defaultPool();

_factoryFeatures = factoryFeatures;
_streamReadFeatures = parserFeatures;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ protected void _checkStdFeatureChanges(int newFeatureFlags, int changedFeatures)
// as per [JACKSON-324], do in finally block
// Also, internal buffer(s) can now be released as well
_releaseBuffers();
_ioContext.close();
}
}
}
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/com/fasterxml/jackson/core/io/IOContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*<p>
* NOTE: non-final since 2.4, to allow sub-classing.
*/
public class IOContext
public class IOContext implements AutoCloseable
{
/*
/**********************************************************************
Expand Down Expand Up @@ -119,6 +119,8 @@ public class IOContext
*/
protected char[] _nameCopyBuffer;

private boolean _closed = false;

/*
/**********************************************************************
/* Life-cycle
Expand Down Expand Up @@ -458,4 +460,12 @@ private IllegalArgumentException wrongBuf() {
// sanity check failed; trying to return different, smaller buffer.
return new IllegalArgumentException("Trying to release buffer smaller than original");
}

@Override
public void close() {
if (!_closed) {
_bufferRecycler.release();
cowtowncoder marked this conversation as resolved.
Show resolved Hide resolved
_closed = true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public void close()
illegalSurrogate(code);
}
}
_context.close();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ public abstract class JsonGeneratorImpl extends GeneratorBase
/**********************************************************
*/

@Override
public void close() throws IOException {
if (!isClosed()) {
super.close();
_ioContext.close();
}
}

@SuppressWarnings("deprecation")
public JsonGeneratorImpl(IOContext ctxt, int features, ObjectCodec codec)
{
Expand Down Expand Up @@ -237,6 +245,23 @@ public JacksonFeatureSet<StreamWriteCapability> getWriteCapabilities() {
return JSON_WRITE_CAPABILITIES;
}

/*
/**********************************************************
/* Misc other accessors
/**********************************************************
*/

/**
* Accessor for use by {@code jackson-core} itself (tests in particular).
*
* @return {@link IOContext} in use by this generator
*
* @since 2.16
*/
public IOContext ioContext() {
return _ioContext;
}

/*
/**********************************************************
/* Shared helper methods
Expand Down
48 changes: 43 additions & 5 deletions src/main/java/com/fasterxml/jackson/core/util/BufferRecycler.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package com.fasterxml.jackson.core.util;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicReferenceArray;

/**
* This is a small utility class, whose main functionality is to allow
* simple reuse of raw byte/char buffers. It is usually used through
* <code>ThreadLocal</code> member of the owning class pointing to
* instance of this class through a <code>SoftReference</code>. The
* end result is a low-overhead GC-cleanable recycling: hopefully
* simple reuse of raw byte/char buffers. It is usually allocated through
* {@link BufferRecyclerPool} (starting with 2.16): multiple pool
* implementations exists.
* The default pool implementation uses
* {@code ThreadLocal} combined with {@code SoftReference}.
* The end result is a low-overhead GC-cleanable recycling: hopefully
* ideal for use by stream readers.
*<p>
* Rewritten in 2.10 to be thread-safe (see [jackson-core#479] for details),
* to not rely on {@code ThreadLocal} access.
* to not rely on {@code ThreadLocal} access.<br />
* Rewritten in 2.16 to work with {@link BufferRecyclerPool} abstraction.
*/
public class BufferRecycler
{
Expand Down Expand Up @@ -82,6 +86,8 @@ public class BufferRecycler
// Note: changed from simple array in 2.10:
protected final AtomicReferenceArray<char[]> _charBuffers;

private BufferRecyclerPool _pool;
cowtowncoder marked this conversation as resolved.
Show resolved Hide resolved

/*
/**********************************************************
/* Construction
Expand Down Expand Up @@ -189,4 +195,36 @@ protected int charBufferLength(int ix) {

protected byte[] balloc(int size) { return new byte[size]; }
protected char[] calloc(int size) { return new char[size]; }

/**
* Method called by owner of this recycler instance, to provide reference to
* {@link BufferRecyclerPool} into which instance is to be released (if any)
*
* @since 2.16
*/
BufferRecycler withPool(BufferRecyclerPool pool) {
if (this._pool != null) {
throw new IllegalStateException("BufferRecycler already linked to pool: "+pool);
}
// assign to pool to which this BufferRecycler belongs in order to release it
// to the same pool when the work will be completed
_pool = Objects.requireNonNull(pool);
return this;
}

/**
* Method called when owner of this recycler no longer wishes use it; this should
* return it to pool passed via {@code withPool()} (if any).
*
* @since 2.16
*/
public void release() {
if (_pool != null) {
BufferRecyclerPool tmpPool = _pool;
// nullify the reference to the pool in order to avoid the risk of releasing
// the same BufferRecycler more than once, thus compromising the pool integrity
_pool = null;
tmpPool.releaseBufferRecycler(this);
}
}
}
Loading