Description
openedon Jan 3, 2024
Alan, Connie and I were discussing the extends-pattern used in the internal class DispositionWork, which extends from AtomicBoolean today. The main reason for this pattern is, this type is in the hot path (e.g. under load, there can be ~2000+ instances of this type in memory per second), the extend-pattern, instead of compose-pattern, saves few bytes per object.
This was a pattern learned from the reactive operator implementation blog Advanced Reactive Java: Operator concurrency primitives: producers (part 1) and used for reactor internal types, some examples - Disposables, BoundedElasticScheduler
. So, we’ve been following this extends-pattern when it is applicable for internal package private types.
We were discussing replacing it with AtomicIntegerFieldUpdater pattern, which offer better readability and avoid need for SE_BAD_FIELD and SE_NO_SERIALVERSIONID exclusions in Spotbug-exclude file.
private static final class DispositionWork {
private volatile int tryCount = 1;
private static final AtomicIntegerFieldUpdater<DispositionWork> TRY_COUNT_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(DispositionWork.class, "tryCount");
private volatile int complete = 0;
private static final AtomicIntegerFieldUpdater<DispositionWork> COMPLETE_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(DispositionWork.class, "complete");
....
But we want to measure AtomicIntegerFieldUpdater against current extends-pattern to ensure updater-pattern is not causing any regression (alloc, perf metrics) and improves the metrics.
Update: Alan checked and JOL layout shows the same width for both patterns. The runtime behavior needs to still measured.