Skip to content

Memory accounting designed off the hot path

Applies to: native operators, Arrow boundary buffers, and native Kafka queues

The accounting itself must not cost throughput. State footprint is tracked incrementally — only the groups a batch touches are re-measured, O(batch) rather than O(open state) — and there is no per-row JNI upcall. Operator state updates its reservation once per processed bundle through a DataFusion MemoryPool; Arrow and Kafka queue allocations reserve at their natural allocation or queue-lifetime boundaries. All of those requests reach one process-wide JVM authority capped by Flink's taskmanager.memory.task.off-heap.size, allowing one operator to use headroom another is not using without exceeding the TaskManager cap. Measured cost of the incremental state sizing was ~2% on the accounted keyed-tumbling bench, statistically unchanged on the unaccounted hot paths (66fcfe3, 2c1c487).

The GROUP BY aggregate's touched-group measurement runs twice per row (before and after the fold), and sizing its cached last-emitted tuple — the same cache described on Aggregate specialization fast paths — re-walked the tuple's ScalarValues each time. A 2026-07-12 q17 profile flagged the cost, so the size is now cached next to the tuple and maintained wherever the cache changes, making the per-row measurement pure arithmetic.