Jackson 3 series companion code
37 runnable examples covering the eight feature posts on ankurm.com, verified against Jackson 3.2.1 on Temurin 21.0.5. Every output committed under docs/ was produced by run-all.sh. Also documents 11 places where the published snippets do not compile or do not behave as printed against a real Jackson 3 build - most notably that writeValueAsString(List<Base>) silently drops the polymorphic type discriminator, so the post's serialised output cannot be read back.
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package com.ankurm.jackson3.beyond;
|
||||
|
||||
import tools.jackson.core.json.JsonFactory;
|
||||
import tools.jackson.core.util.JsonRecyclerPools;
|
||||
import tools.jackson.core.util.RecyclerPool;
|
||||
import tools.jackson.databind.json.JsonMapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* BEYOND THE POSTS — the performance knob the comparison post names but never measures.
|
||||
*
|
||||
* Jackson 3 changed the default buffer RecyclerPool. The post says to restore the 2.x
|
||||
* thread-local pool if you see a regression. Whether that helps depends entirely on your
|
||||
* concurrency profile, so this measures it on the machine you are actually running on
|
||||
* instead of asserting a winner.
|
||||
*
|
||||
* Indicative timings, not JMH. Run it a few times; the numbers move.
|
||||
*/
|
||||
public class Y06RecyclerPoolTuning {
|
||||
|
||||
public record Payload(long id, String name, List<String> tags, double amount) { }
|
||||
|
||||
private static final int ITERATIONS = 40_000;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("default pool : "
|
||||
+ JsonRecyclerPools.defaultPool().getClass().getSimpleName());
|
||||
System.out.println("cores : " + Runtime.getRuntime().availableProcessors());
|
||||
System.out.println();
|
||||
|
||||
for (int threads : new int[] { 1, 8 }) {
|
||||
System.out.println("--- " + threads + " thread(s), " + ITERATIONS + " round-trips each ---");
|
||||
run(threads, "threadLocalPool (2.x default)", JsonRecyclerPools.threadLocalPool());
|
||||
run(threads, "concurrentDeque (3.x default)", JsonRecyclerPools.newConcurrentDequePool());
|
||||
run(threads, "nonRecyclingPool (no reuse) ", JsonRecyclerPools.nonRecyclingPool());
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
private static void run(int threads, String label, RecyclerPool<?> pool) throws Exception {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
JsonFactory factory = JsonFactory.builder().recyclerPool((RecyclerPool) pool).build();
|
||||
JsonMapper mapper = JsonMapper.builder(factory).build();
|
||||
|
||||
Payload sample = new Payload(1L, "example", List.of("a", "b", "c"), 12.5);
|
||||
for (int i = 0; i < 2_000; i++) { // warm up
|
||||
mapper.readValue(mapper.writeValueAsString(sample), Payload.class);
|
||||
}
|
||||
|
||||
ExecutorService pooled = Executors.newFixedThreadPool(threads);
|
||||
long start = System.nanoTime();
|
||||
var tasks = java.util.stream.IntStream.range(0, threads)
|
||||
.<Callable<Void>>mapToObj(t -> () -> {
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
mapper.readValue(mapper.writeValueAsString(sample), Payload.class);
|
||||
}
|
||||
return null;
|
||||
}).toList();
|
||||
for (var future : pooled.invokeAll(tasks)) future.get();
|
||||
long ms = (System.nanoTime() - start) / 1_000_000;
|
||||
pooled.shutdown();
|
||||
|
||||
System.out.printf(" %-34s %5d ms%n", label, ms);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user