Add AIMD based dynamic producer batch sizing to JCQueue#8796
Add AIMD based dynamic producer batch sizing to JCQueue#8796GGraziadei wants to merge 2 commits into
JCQueue#8796Conversation
Performance analysisThe benchmarks were run against the Attached raw data and report. |
|
@GGraziadei thanks for the submission. Overall it looks good. A. Non-Static ThreadLocal Memory Leak CycleThe PR defines the thread-local fields as instance variables of JCQueue : In Java, this creates a cyclic reference cycle: • Thread holds ThreadLocalMap . Even if the JCQueue reference is discarded elsewhere, it cannot be garbage collected because it is reachable from the thread's map, which prevents the key from being weakly cleared. │ [!NOTE] B. Transient Backpressure SmoothingIn tryFlush() , when the queue is full under backpressure, tryPublishInternal returns 0. The method returns false but still executes the afterFlush(wasFull) hook: If wasFull was true , effectiveBatchSz increases. │ [!TIP] |
|
Hi @reiabreu, Thanks for scanning this PR with an agent, I think it is a really good practice to always get new insights to reflect on. Regarding point A, I think your analysis makes total sense. At the same time, we are running into one of Java's biggest limitations, which is its memory management. I perfectly understand the highlighted issue and it is real. In other programming languages with direct memory management (like Rust or C++), for example, I remember the solution is simply to call the destructor when a weak reference no longer exists. In Rust, for instance, I remember using special smart pointers like It certainly won't call a destructor, but I believe it will be useful at the GC level to break the reference cycle. Since this pattern was already pre-existing and requires some proper refactoring, I have opened this dedicated issue to fix it later: #8810 Regarding point B: Your reconstruction is spot on, and this behavior is entirely intentional. A full batch that the Thanks for the deep dive and the feedback! |
What is the purpose of the change
This PR introduces an adaptive batch-sizing strategy for
JCQueue'sproducer-side inserter, controlled by a new feature flag (topology.producer.batch.dynamic). Instead of committing to a fixedproducerBatchSz, the newDynamicBatchInserterstarts at a batch size of 1 and adjusts it online using AIMD: it additively grows the effective size (+1) after flushing a full batch (heavy load) and multiplicatively shrinks it (halving toward 1) after a timer-driven partial flush (light load), with the configured batch size acting as a ceiling rather than a fixed target. This lets the queue favor low latency under light load while preserving throughput under sustained back-pressure, without manual per-topology tuning.How was the change tested
BatchInserter(baseline) vsDynamicBatchInserter, report in the first comment.