Skip to content

perf(node): cut ack re-encode, exact stanza sizing, warm session pre-filter - #1018

Merged
jlucaso1 merged 2 commits into
mainfrom
perf/node-path-allocs
Jul 10, 2026
Merged

perf(node): cut ack re-encode, exact stanza sizing, warm session pre-filter#1018
jlucaso1 merged 2 commits into
mainfrom
perf/node-path-allocs

Conversation

@jlucaso1

Copy link
Copy Markdown
Collaborator

Summary

  • Ack → waiter without re-encode: resolving a response waiter for an <ack> re-encoded the node (1 KiB marshal + Bytes copy + re-parse) even though every caller already has the node owned or shared. The read-loop fast path now hands its OwnedNodeRef straight into the waiter's Arc and shared callers clone the Arc; the borrow-only re-encode entry point had no remaining callers and is removed.
  • Exact stanza sizing on send_node: the one-pass encoder reserved its 1 KiB default for every outgoing stanza; typical live stanzas are a few hundred bytes. Switched to the existing exact two-pass path.
  • Warm-cache pre-filter in ensure_sessions: the buffer_unordered probe machinery was built even when every session was already cached. A synchronous try_has_session pre-filter short-circuits the warm case; contended or unknown entries still take the async probe and the backend.

Impact

DHAT ping-pong (2000 cycles, connect-subtracted, average of 2 runs, baseline = main @ d9141ac with AC power): allocation cost per cycle dropped from 36,248.3 to 35,169.6 bytes (-3.0%) and from 226.84 to 219.79 blocks (-3.1%). No extra retention at exit, 2000/2000 pongs with 0 lost in both runs. Timed CPU runs were inconclusive (hybrid-CPU run-to-run variance exceeds the effect size).

Cumulative since the start of this allocation series (pre-#1015 baseline of 46,088 B/cycle): -23.7% bytes per cycle.

Validation

  • cargo test -p whatsapp-rust --lib (976 passed; new tests: the Arc entry point delivers the original allocation via Arc::ptr_eq, the owned entry point resolves waiters, warm-cache ensure short-circuits while a cold probe still attempts the fetch)
  • cargo test -p wacore --lib (1080 passed)
  • cargo clippy -p whatsapp-rust -p wacore --lib --tests -- -D warnings
  • RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo check -p whatsapp-rust --lib --target wasm32-unknown-unknown --no-default-features

…filter

Three hot-path allocation cuts on the live message cycle:

- Resolving a response waiter for an <ack> re-encoded the node (1 KiB
  marshal + Bytes copy + re-parse) even though every caller already has
  the node owned or shared. Split the entry points: the read-loop fast
  path hands its OwnedNodeRef straight into the waiter's Arc and shared
  callers clone the Arc. The borrow-only re-encode path had no remaining
  callers and is gone.

- send_node serialized every stanza through the one-pass encoder with
  its 1 KiB default reserve; typical stanzas are a few hundred bytes.
  Use the exact two-pass sizing instead.

- ensure_sessions built the buffer_unordered probe machinery even when
  every session was already cached. A synchronous try_has_session
  pre-filter short-circuits the warm case; contended or unknown entries
  still take the async probe.
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6c2768aa-efb6-483c-8b09-cc049c9efad5

📥 Commits

Reviewing files that changed from the base of the PR and between 549f616 and 9e12104.

📒 Files selected for processing (1)
  • src/client/node_io.rs

📝 Walkthrough

Summary by CodeRabbit

  • Performance Improvements
    • Improved message transmission by using exact payload sizing before sending.
    • Reduced acknowledgment processing overhead by avoiding re-encoding when delivering ACKs already in memory.
    • Warm session checks now short-circuit earlier, avoiding unnecessary probe work.
  • Reliability
    • Enhanced acknowledgment delivery logic to keep waiter resolution consistent while maintaining server acknowledgment event emission.
  • Tests
    • Updated and expanded ACK handling tests (including allocation/regression checks).
    • Added an integration test covering warm-cache short-circuiting for session resolution.

Walkthrough

The PR refactors ACK waiter delivery to reuse owned node representations, filters cached sessions before probing, and switches outgoing stanza serialization to exact-size marshaling. Tests cover ACK delivery, allocation behavior, server ACK events, and cached-session short-circuiting.

Changes

ACK delivery refactor

Layer / File(s) Summary
ACK fast paths and waiter delivery
src/client/node_io.rs, src/handlers/basic.rs, src/client/tests.rs
ACK dispatch now uses Arc- and owned-node handlers, removes waiter re-encoding, and validates delivery, event dispatch, allocation behavior, and unmatched ACKs.

Session cache short circuit

Layer / File(s) Summary
Warm-cache session filtering
src/client/sessions.rs, src/client/tests.rs
Session ensuring filters cached JIDs and returns early when all requested sessions are already available, with cold- and warm-cache coverage.

Exact stanza marshaling

Layer / File(s) Summary
Exact-size outgoing marshaling
src/client/messaging.rs
Client::send_node uses marshal_exact before sending raw stanza bytes while retaining existing error handling.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AckHandler
  participant Client
  participant ResponseWaiter
  AckHandler->>Client: handle_ack_response_arc(Arc<OwnedNodeRef>)
  Client->>Client: take_ack_waiter(ack_id)
  Client->>ResponseWaiter: send existing Arc node
Loading

Possibly related PRs

Suggested labels: performance

Suggested reviewers: cubic-dev-ai, greptile-apps

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the three main performance changes in the PR.
Description check ✅ Passed The description accurately matches the changeset and explains the performance impact and validation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/node-path-allocs

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 10, 2026

Copy link
Copy Markdown

Greptile Summary

This PR reduces allocation work in the node send and ack paths. The main changes are:

  • Outgoing stanzas now use exact binary marshal sizing.
  • Ack waiters receive the existing owned node allocation instead of a re-encoded copy.
  • Warm cached sessions skip the async probe setup in ensure_sessions.
  • Tests cover ack allocation sharing, owned ack delivery, and warm-cache session behavior.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
src/client/messaging.rs send_node now uses exact marshal sizing for outgoing stanzas.
src/client/node_io.rs Ack handling now has owned and shared node entry points for waiter resolution.
src/client/sessions.rs ensure_sessions_inner now skips async probing when the session cache already has every session.
src/handlers/basic.rs The ack handler forwards the shared owned node to the ack waiter path.
src/client/tests.rs Tests were updated for exact ack delivery behavior and warm-cache session short-circuiting.

Reviews (2): Last reviewed commit: "refactor(ack): share the rejected-waiter..." | Re-trigger Greptile

Comment thread src/client/messaging.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/client/node_io.rs`:
- Around line 1143-1174: Deduplicate the identical rejected-waiter warning in
handle_ack_response_arc and handle_ack_response_owned by extracting it into a
small shared helper, then call that helper from both send error branches while
preserving the existing target, message, and rejected node ID.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 00f2cb11-6df4-4221-a971-a84be629d259

📥 Commits

Reviewing files that changed from the base of the PR and between d9141ac and 549f616.

📒 Files selected for processing (5)
  • src/client/messaging.rs
  • src/client/node_io.rs
  • src/client/sessions.rs
  • src/client/tests.rs
  • src/handlers/basic.rs

Comment thread src/client/node_io.rs
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

📦 Binary size report

Metric main PR Δ
bin size (stripped) 10.84 MiB 10.83 MiB -5.16 KiB (-0.05%) 🔽
bin .text 8.84 MiB 8.83 MiB -5.56 KiB (-0.06%) 🔽
bin allocated (text+data+bss) 10.84 MiB 10.83 MiB -4.28 KiB (-0.04%) 🔽
llvm-lines wacore 506,082 506,082 0
llvm-lines wacore copies 17,369 17,369 0
llvm-lines whatsapp-rust lib 770,790 770,998 +208 (+0.03%) 🔺
llvm-lines whatsapp-rust lib copies 25,007 25,020 +13 (+0.05%) 🔺
deps crates (Cargo.lock) 472 472 0
.text per crate
Crate main PR Δ
.text whatsapp_rust 1.65 MiB 1.65 MiB +1.11 KiB (+0.07%) 🔺
.text wacore 526.97 KiB 527.50 KiB +548 B (+0.10%) 🔺
.text wacore_binary 157.88 KiB 149.42 KiB -8.46 KiB (-5.36%) 🎉
.text wacore_libsignal 179.42 KiB 179.42 KiB 0
.text wacore_appstate 158.25 KiB 158.25 KiB 0
.text wacore_noise 26.05 KiB 26.05 KiB 0
.text waproto 1.60 MiB 1.60 MiB 0
.text whatsapp_rust_sqlite_storage 513.00 KiB 513.00 KiB 0
.text whatsapp_rust_tokio_transport 43.79 KiB 43.79 KiB 0
.text whatsapp_rust_ureq_http_client 10.47 KiB 10.47 KiB 0
.text std 1.00 MiB 1.00 MiB +1.23 KiB (+0.12%) 🔺
.text other deps 2.95 MiB 2.95 MiB 0
Top movers (cargo-bloat attribution)
Crate main PR Δ
wacore_binary 157.88 KiB 149.42 KiB -8.46 KiB (-5.36%)
std 1.00 MiB 1.00 MiB +1.23 KiB (+0.12%)
whatsapp_rust 1.65 MiB 1.65 MiB +1.11 KiB (+0.07%)

Baseline: d9141ac0c (latest main run) · Head: 03448ecab · Graphs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Confidence score: 5/5

  • Safe to merge after the addressed issues were fixed.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/client/node_io.rs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Auto-approved: Performance optimizations for ack handling, marshalling, and session caching, with added tests; low risk, well-contained changes.

Re-trigger cubic

@jlucaso1
jlucaso1 merged commit d2d6046 into main Jul 10, 2026
30 checks passed
@jlucaso1
jlucaso1 deleted the perf/node-path-allocs branch July 10, 2026 23:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant