Skip to content

perf(core): flatten demux filter chain into a vector#188

Merged
loyd merged 2 commits into
elfo-rs:masterfrom
Leonqn:perf/flatten-demux-filters
Apr 9, 2026
Merged

perf(core): flatten demux filter chain into a vector#188
loyd merged 2 commits into
elfo-rs:masterfrom
Leonqn:perf/flatten-demux-filters

Conversation

@Leonqn

@Leonqn Leonqn commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace nested closure chain in Demux with a flat SmallVec of filters
  • Add mailbox benchmark measuring per-call cost of send/try_send (routed and direct) across 1–100 consumer groups
  • Enable full feature for bench crate (needed for elfo-configurer)

Previously each route_to wrapped the previous filter in a new closure, creating a recursive call chain. With many groups (50+) this caused overhead due to deep indirect calls and CPU cache misses. The flat vector iterates filters sequentially.

Benchmark results

send_routed (ns per call, system allocator):

Groups Nested closures Flat vector Change
1 227 230 ~0%
10 735 716 ~0%
30 812 822 ~0%
50 1106 847 -24%
75 1274 874 -32%
100 1670 883 -47%

try_send_routed (ns per call, system allocator):

Groups Nested closures Flat vector Change
1 182 179 ~0%
10 717 692 ~0%
30 794 759 -5%
50 1175 777 -34%
75 1351 809 -40%
100 1694 841 -50%

Test plan

  • All existing tests pass
  • New mailbox_sys benchmark passes (cargo bench --bench mailbox_sys -- --test)
  • Existing messaging_sys benchmark compiles and runs

@Leonqn Leonqn force-pushed the perf/flatten-demux-filters branch from 9ce73ff to 5cc5a1a Compare April 7, 2026 09:58
@codecov

codecov Bot commented Apr 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@loyd

loyd commented Apr 9, 2026

Copy link
Copy Markdown
Collaborator

I've also tried using the dynstack crate instead to avoid Arc<dyn Fn>, but it seems the difference is negligible:

group                      b188                                   dynstack
-----                      ----                                   --------
send_routed/100g32w        1.01   612.5±66.64ns        ? ?/sec    1.00  607.9±113.70ns        ? ?/sec
send_routed/10g32w         1.04   507.8±92.74ns        ? ?/sec    1.00   489.9±69.34ns        ? ?/sec
send_routed/1g32w          1.04   173.8±68.22ns        ? ?/sec    1.00   167.1±48.85ns        ? ?/sec
send_routed/20g32w         1.01   517.3±60.31ns        ? ?/sec    1.00   514.1±80.83ns        ? ?/sec
send_routed/2g32w          1.00   329.1±47.56ns        ? ?/sec    1.05   344.9±95.70ns        ? ?/sec
send_routed/30g32w         1.03   532.9±92.16ns        ? ?/sec    1.00   519.2±80.79ns        ? ?/sec
send_routed/50g32w         1.05  599.9±152.40ns        ? ?/sec    1.00  569.4±117.64ns        ? ?/sec
send_routed/5g32w          1.00   426.5±45.50ns        ? ?/sec    1.05   446.3±66.93ns        ? ?/sec
send_routed/75g32w         1.00  636.7±151.27ns        ? ?/sec    1.02  652.2±300.52ns        ? ?/sec
try_send_routed/100g32w    1.06  652.3±187.36ns        ? ?/sec    1.00  613.2±172.57ns        ? ?/sec
try_send_routed/10g32w     1.00   499.8±93.48ns        ? ?/sec    1.02   511.0±96.79ns        ? ?/sec
try_send_routed/1g32w      1.07   146.7±39.16ns        ? ?/sec    1.00   137.2±19.96ns        ? ?/sec
try_send_routed/20g32w     1.02   521.3±84.37ns        ? ?/sec    1.00   512.6±61.14ns        ? ?/sec
try_send_routed/2g32w      1.05   336.1±66.64ns        ? ?/sec    1.00   320.4±79.08ns        ? ?/sec
try_send_routed/30g32w     1.00   522.4±54.15ns        ? ?/sec    1.00   524.5±69.52ns        ? ?/sec
try_send_routed/50g32w     1.08  593.7±222.96ns        ? ?/sec    1.00   551.6±77.44ns        ? ?/sec
try_send_routed/5g32w      1.08   464.5±53.77ns        ? ?/sec    1.00   430.8±62.59ns        ? ?/sec
try_send_routed/75g32w     1.00   583.7±84.81ns        ? ?/sec    1.02  593.4±202.98ns        ? ?/sec

@loyd

loyd commented Apr 9, 2026

Copy link
Copy Markdown
Collaborator

I decided to merge these changes without the mailbox.rs benchmark because it mostly duplicates the existing messaging.rs, adding only not very common axes like the number of groups.

@loyd loyd merged commit 6a90911 into elfo-rs:master Apr 9, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants