bench(client): receive one message from the decoded stanza to the event - #1392
Conversation
`wacore`'s `send_receive_benchmark` covers the pure decrypt, and both DM
and group receives there sit within a few microseconds of their crypto
floor. Everything around the decrypt lives in the client crate and had
no benchmark: classification, the signal-cache checkout, dedup and
retry bookkeeping, plaintext handling, the event bus, the delivery
receipt. `ReceiveHarness` is the inbound twin of `GroupSendHarness`: a
second in-memory client is the peer, holding an acknowledged pairwise
session and a sender key installed through the real SKDM handler, and
encrypts every measured stanza; the receiving client takes it at
`handle_incoming_message`, which is what the chat-lane worker awaits per
message, so the queue hop is excluded and the per-message work is not.
Each bench asserts the subscriber saw every message, since a failed
decrypt is fast and would otherwise pass for a receive.
First numbers, current-thread runtime, in-memory backend:
dm_receive 13.5 µs (pure decrypt: 10.5 µs)
group_receive 50.8 µs (pure decrypt: 42.8 µs)
Under callgrind, `handle_incoming_message_scoped` is 73% session
decrypt for a DM and 79% signature verification for a group message;
the client's own share is about 25k instructions per DM.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172fpxasGTrouFyYH5UGmjN
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Team Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 4 included reviews per hour; 0 remain after this review. Important Approval pendingCodeRabbit has no unresolved comments, but it has not reviewed the latest commit. Use the checkbox below to review the latest commit. CodeRabbit will approve the changes if it finds no blocking issues.
📝 SummarySummary by CodeRabbit
WalkthroughAdds client-level DM and group receive benchmarks. The change adds a warmed in-memory encrypted-message fixture, benchmark-enabled receive handling, delivery-count validation, and Cargo benchmark registration. ChangesClient receive benchmarks
Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: ⚪ Minimal · up to This change adds opt-in receive benchmarks and an in-memory test fixture without changing ordinary production behavior or external interfaces. No actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant Divan
participant ReceiveHarness
participant Client
participant MessageEvents
Divan->>ReceiveHarness: build encrypted DM or group stanza
Divan->>Client: receive decoded stanza
Client->>MessageEvents: dispatch message event
Divan->>MessageEvents: verify delivered-message count
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
| Filename | Overview |
|---|---|
| benches/client_receive.rs | Adds direct-message and group-message receive benchmarks with delivery assertions. |
| src/bench_support.rs | Adds the peer-backed receive fixture, encrypted stanza builders, event counter, and outbound flushing. |
| src/message/receive.rs | Makes the existing test-only inbound helper available under the benchmark-harness feature. |
| Cargo.toml | Registers the feature-gated client_receive benchmark target. |
Sequence Diagram
sequenceDiagram
participant Bench as Divan benchmark
participant Peer as In-memory peer
participant Client as Receiving client
participant Signal as Signal stores
participant Events as Event subscriber
participant Sink as Sink transport
Bench->>Peer: Build encrypted DM/group stanza
Peer->>Signal: Advance session or sender-key chain
Peer-->>Bench: Decoded message node
Bench->>Client: handle_incoming_message(node)
Client->>Signal: Decrypt payload
Signal-->>Client: Plaintext message
Client->>Events: Dispatch Event::Messages
Client->>Sink: Queue encrypted delivery receipt
Bench->>Client: Flush outbound receipt work
Bench->>Events: Assert delivered count
Reviews (3): Last reviewed commit: "bench(client): keep the delivery receipt..." | Re-trigger Greptile
The receive harness doc linked `Client::handle_incoming_message`, which is pub(crate), and rustdoc under `-D warnings` rejects a public item linking to a private one. A plain code span says the same thing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0172fpxasGTrouFyYH5UGmjN
Dismissed because a newer commit was pushed; Greptile will re-review the current head.
|
Semver Checks (informational) is red on this head and is not this PR's: the job diffs Generated by Claude Code |
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0172fpxasGTrouFyYH5UGmjN
There was a problem hiding this comment.
All reported issues were addressed
You’re at about 95% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 1 file (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
You’re at about 95% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.
Re-trigger cubic
`ack_received_message` hands the receipt to a detached worker, so
`handle_incoming_message` returned before it was marshalled and
noise-encrypted, and on the harness's current-thread runtime that work
ran during the next iteration's await instead. `receive` now flushes the
outbound scope, which pulls the receipt into the measured region:
dm_receive 13.5 µs -> 20.6 µs
group_receive 50.8 µs -> 72.6 µs
The difference is the receipt path's own cost, which the benchmark was
built to expose and had been hiding.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172fpxasGTrouFyYH5UGmjN
Dismissed because a newer commit was pushed; Greptile will re-review the current head.
There was a problem hiding this comment.
0 issues found across 1 file (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
You’re at about 96% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Auto-approved: Adds client-level receive benchmarks and supporting bench-only harness code, with no production behavior changes; the only non-test gate is widened to the bench-harness feature for an internal test helper.
Re-trigger cubic
📦 Binary size report
.text per crate
Baseline: |
|
Correction to the numbers in the description, from an A/B on one binary after the merge: the delivery receipt plus its worker hand-off costs about 5 µs on a DM receive, not 7, and on a group receive the difference is within this host's noise, not 22 µs. The description's "without the receipt" column came from an earlier run on a quieter machine state; measured back to back, no-wait vs. timed flush vs. listener vs. yield loop give 15 / 20 / 20 / 19 µs for Generated by Claude Code |
Summary
The client crate had a benchmark for the send path (
client_group_send) and none for the receive path, which is where #1389 and #1390 spent most of their effort. This addsclient_receive, the inbound twin of the group-send harness, so that work is regression-gated on CodSpeed from here on.ReceiveHarness(bench_support, behindbench-harness): a second in-memory client is the peer. It holds an acknowledged pairwise session (reusing the same two-way X3DH the send harness needs for its companion, which now returns the peer instead of dropping it) and a sender key installed through the real SKDM handler, and it encrypts every measured stanza. The receiving client takes each stanza athandle_incoming_message, which is what the chat-lane worker awaits per message, so the queue hop is excluded by construction and the per-message work is not: classification, the signal-cache checkout, dedup and retry bookkeeping, plaintext handling, dispatch, and the delivery receipt marshalled and noise-encrypted onto the sink socket. The receipt rides a detached worker, soreceiveflushes the outbound scope before returning; without that the receipt's cost leaked into the next iteration (cubic caught this).dm_receiveandgroup_receive. Each asserts that the subscribed handler saw every message it received, because a failed decrypt is fast and would otherwise pass for a receive.handle_incoming_message(test-only before) is also available underbench-harness.The CodSpeed
clientshard already builds the whole crate with--features bench-harness, so the new target runs without a workflow change.Numbers
Current-thread runtime, in-memory backend, this container:
wacore)dm_receivegroup_receiveUp to the dispatched event the client is within a few microseconds of its crypto floor: under callgrind,
handle_incoming_message_scopedis 73% session decrypt for a DM and 79% XEdDSA verification for a group message, and the client's own share is about 25k instructions per DM. The delivery receipt is the one thing this benchmark found that was not already known: 7 µs on a DM and 22 µs on a group message, which is the next thing to look at, and now has a number to move.The "left out" items from #1390 measure below the noise (a
SenderKeyRecordclone is 149 ns against a 44 µs group decrypt; a precomputed per-sender verification table changes nothing, since the 256 doublings dominate).Validation
cargo fmt --all,cargo clippy -p whatsapp-rust --features bench-harness --all-targets -- -D warnings,cargo check -p whatsapp-rust --lib(feature off),RUSTDOCFLAGS="-D warnings" cargo doc -p whatsapp-rust --all-features --no-depsclean.cargo bench -p whatsapp-rust --features bench-harness --bench client_receiveruns both benches with their delivery assertions passing.🤖 Generated with Claude Code
https://claude.ai/code/session_0172fpxasGTrouFyYH5UGmjN