Decouple the control plane from the data plane on receive queues#8892
Decouple the control plane from the data plane on receive queues#8892GGraziadei wants to merge 2 commits into
Conversation
|
Thanks @reiabreu, your intuition was entirely correct. Using a streaming grouping driven by a feedback control loop is fundamental to decoupling the control plane from the data plane. In particular, enabling Here are the key takeaways from the performance scenarios:
In conclusion, it makes sense to keep the dedicated control queue (CQ) optional. It should not be enabled by default. Jitter-Aware Stream Grouping_ Decoupling the Control Queue.pdf Evaluating the Effect of the Control Queue in a Backpressured Scenario.pdf Evaluating the cost of a separate Control Queue.pdf Raw data: |
|
Thx for the PR. The overall design looks good to me: opt-in, default off and well tested. A few things I would like to see changed before merging:
The remaining behavioral risks (control tuples overtaking co-enqueued data, drop instead of block) are fine with me as long as they are documented as per point 2. |
- simplify Constants.isControlStreamId: drop the static-init bitmask fast
path in favor of startsWith("__") + set lookup (same behavior, less to
maintain)
- document that __tick tuples may be dropped under saturation when the
lane is enabled (Config javadoc + docs/Performance.md), so bolts using
ticks for windowing/expiry tolerate an occasional miss
- log a rate-limited WARN in JCQueue.tryPublishControl when a control
tuple is dropped, so a stalled executor is visible in the logs and not
only via the control_dropped_messages metric
- note on the controlQueue field that close() does not drain the lane,
matching recvQueue behavior
- fix import order in JCQueueTest
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Hi @rzo1, I have just pushed a commit that addresses all your points. Interestingly, to address most of the documentation, logging, and nitpick fixes, I ran an experiment and let Claude handle them directly. I'm sure you're already familiar with these tools, but the agent did a good job. It feels like projects like Apache Magpie might really be just around the corner? On my end, I focused on the micro-benchmarking to see if the bitmask for Here are the results of the JMH microbenchmark (2 forks, 10 measured iterations per case, JDK 25, jvm warmup discarded) comparing the bitmask against the simplified
Even if we consider a worst-case scenario where a sequence of these edge-case IDs adds around 5 ns per check, across a standard path size of 10 to 100 hops (considering the order of magnitude), the cumulative latency increase would be roughly ~500 ns. Given that per-tuple processing overhead is measured in microseconds, this is completely negligible. Since real topologies are dominated by user data streams and genuine control tuples, the ~30 lines of fragile static-init machinery are optimizing a case that doesn't realistically occur. I completely agree that simplifying the code and using a standard HashSet is the right call. The clean-up is included in the latest commit. |
|
@GGraziadei thanks for this great work and for the detailed performance reports. |
What is the purpose of the change
Fixes #8816
A Storm executor multiplexes two fundamentally different kinds of traffic onto its single inbound JCQueue:
traffic that backpressure is meant to throttle.
This PR introduces an optional control receive queue. When enabled, this dedicated queue is prioritized and completely drained before the standard data queue is processed. This ensures that critical coordination traffic bypasses data plane bottlenecks.
For additional context and technical details, please refer to the discussion inside the issue thread.
How was the change tested