-
Notifications
You must be signed in to change notification settings - Fork 109
Open
Description
Since DslJson is made to be used with object pooling, there would be nice if the framework provided an object pool as well. I've made the implementation below which we use internally at our organization. Would such a class be a good idea to include with the framework? If so feel free to use it.
/**
* Object pooling of JsonWriter objects from DslJson for peak performance.
* The JsonWriter objects keep an internal byte-array as an in-memory buffer
* for the serialized json data. The parameter 'initialBufferSize' is the
* initial size of the byte-array and should be tuned to the specific json
* payload so that resizing during serialization rarely happens (expensive).
*/
public class DslJsonWriterPool<T> {
private final DslJson<T> dslJson;
// High performance thread safe queue used for object pooling.
private final ConcurrentLinkedQueue<JsonWriter> pool = new ConcurrentLinkedQueue<>();
// Manual pool size count since calling pool.size() is expensive and also inaccurate according to docs.
private final AtomicInteger poolSize = new AtomicInteger();
// Take memory usage into account for the max size.
private final int maxPoolSize;
// Tune the initial buffer size to the json payload so that buffer resizing rarely happens (expensive).
private final int initialBufferSize;
// Avoids pooling too large buffers, resizing might cause buffers to get very large during serialization.
private final int maxBufferSize;
public DslJsonWriterPool(DslJson<T> dslJson) {
this(dslJson, 100, 1024, 11264); // Good default pool size and buffer sizes for most objects.
}
public DslJsonWriterPool(DslJson<T> dslJson, int maxPoolSize, int initialBufferSize, int maxBufferSize) {
if (initialBufferSize > maxBufferSize) throw new IllegalArgumentException("initialBufferSize cannot be greater than maxBufferSize");
this.dslJson = dslJson;
this.maxPoolSize = maxPoolSize;
this.initialBufferSize = initialBufferSize;
this.maxBufferSize = maxBufferSize;
}
public JsonWriter borrowWriter() {
var writer = pool.poll();
if (writer != null) {
poolSize.decrementAndGet();
return writer;
}
return dslJson.newWriter(initialBufferSize);
}
public void returnWriter(JsonWriter writer) {
if (poolSize.get() >= maxPoolSize) return;
if (writer.getByteBuffer().length > maxBufferSize) return;
writer.reset(); // Reset internal buffer position.
if (pool.offer(writer)) poolSize.incrementAndGet();
}
public int getPoolSize() {
return poolSize.get();
}
}
Typical usage of the pool below.
public class PoolExample {
@CompiledJson
record InfoData(
String field1,
String field2,
String field3) {
}
DslJson<InfoData> dslJson = new DslJson<>();
DslJsonWriterPool<InfoData> pool = new DslJsonWriterPool<>(dslJson);
void main() {
var infoData = new InfoData("1", "2", "3");
JsonWriter writer = null;
try {
writer = pool.borrowWriter();
dslJson.serialize(writer, infoData);
System.out.write(writer.getByteBuffer(), 0, writer.size());
} catch (Throwable th) {
System.out.println("Log error: " + th);
} finally {
if (writer != null)
pool.returnWriter(writer);
}
}
}
Metadata
Metadata
Assignees
Labels
No labels