Speed up fanout exchange (backport #14546) #14563
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Resolves #14531
Resolves #14533
What?
Increase end-to-end message throughput for messages routed via the fanout exchange by ~42% (see benchmark below).
In addition to the fanout exchange, a similar speed up is achieved for the following exchange types:
This applies only if Khepri is enabled.
How?
Use an additional routing table (projection)
rabbit_khepri_route_by_sourcewhose table key is the source exchange.Looking up the destinations happens then by an ETS table key.
Prior to this commit, CPUs were busy compiling the same match spec for every incoming message.
For the bug fix of #14533, we also introduce a new projection called
rabbit_khepri_route_by_source_key. This can be thought of a v2 of the oldrabbit_khepri_index_routeprojection. The oldrabbit_khepri_index_routeprojection gets deleted in therabbitmq_4.2.0feature flag callback. The two new projections are registered at boot time (as discussed in #14543 (comment))Benchmark
where
advanced.configcontains:Before this commit:
After this commit:
The CPU flamegraph shows that
rabbit_exchange:route/3consumes the following CPU amounts:Downsides
Additional ETS memory usage for the new projection table.
However, the new table does not store any binding entries for the following
source exchange types:
Also, care must be taken to not add extensive amounts of bindings with the same source exchange to projection
rabbit_khepri_route_by_source. For fanout exchanges, binding an extensive amount of queues (e.g. thousands) to the same fanout exchanges is nonsensical anyway. One edge case could be binding thousands of queues to therandomexchange type. But even such an exotic use case could be realised efficiently by using intermediate random exchanges (i.e. exchange-to-exchange bindings) 🙂This is an automatic backport of pull request #14546 done by Mergify.