Skip to content

bench: cover four inbound/group hot paths for CodSpeed baselines - #858

Merged
jlucaso1 merged 1 commit into
mainfrom
bench/inbound-hotpaths
Jun 12, 2026
Merged

bench: cover four inbound/group hot paths for CodSpeed baselines#858
jlucaso1 merged 1 commit into
mainfrom
bench/inbound-hotpaths

Conversation

@jlucaso1

@jlucaso1 jlucaso1 commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Why

Establishes CodSpeed baselines for four receive-path hot paths that had no benchmark coverage, so a flamegraph can then point at where to optimize. No production code changes — benchmarks only. (#856 already covered the two biggest inbound gaps, plaintext decode and the appstate index-MAC dedup; this fills the rest.)

What it adds

  • bench_parse_message_info (message_utils_benchmark) — the stanza→MessageInfo metadata parse that runs once per inbound message before any Signal work, across four shapes (DM, LID group, status broadcast, self-sent). The input is a marshal round-trip decoded back into an OwnedNodeRef, so JID attributes arrive wire-typed (ValueRef::Jid) exactly as the decoder hands them to the receive loop — not string-parsed via Jid::from_str, which production never does. Each shape carries an <enc> child so the get_optional_child scans run.
  • bench_decode_record (appstate_benchmark) — the per-mutation app-state decode (AES-256-CBC + content HMAC-SHA512 + index HMAC-SHA256 + prost + JSON index parse), up to ~1000× per resume patch. process_patch covered the whole loop but never isolated this inner per-record cost. Two shapes (5-part STAR index, contact-name) built via encode_record so MAC validation runs the success path.
  • bench_group_out_of_order_decrypt_worst_case (libsignal_benchmark) — a ~2000-deep skipped-key backlog, the full out-of-order group decrypt. Honest framing in the doc: the backlog-sized SenderKeyRecord clone in load_sender_key and the signature check are the bulk of it, with the O(n) remove_sender_message_key scan a smaller slice — a baseline, not a scan-isolating microbench. (The clone showing up this large is itself a lead worth a flamegraph look.)
  • bench_process_sender_key_distribution_message (libsignal_benchmark) — SKDM ingest into a fresh store, the first-group-message-per-sender cost, previously executed only in other benches' setup.

Precision

Every bench black_boxes its inputs and fully observes its output (the thin-LTO dead-code-elimination lesson from the reporting-token bench), and keeps all expensive setup in with_inputs (untimed). Drafted in parallel and then adversarially verified via a workflow — that pass caught and fixed the two issues above (the string-typed vs wire-typed JID realism gap in parse_message_info, which had overstated it ~25-43% and skewed the profile toward a from_str the receive loop never runs; and the misleading scan-only framing of the group OOO bench). No Cargo.toml changes (all bench targets already registered); cargo clippy --workspace --all-targets clean.

Review in cubic

Adds divan benchmarks (no production code change) for receive-path hot
paths that had no coverage, so CodSpeed can establish baselines and a
flamegraph can show where to optimize:

- parse_message_info: stanza->MessageInfo metadata parse, once per inbound
  message. Input is a marshal round-trip decoded back to OwnedNodeRef, so
  JID attrs arrive wire-typed (ValueRef::Jid) exactly as the decoder hands
  them to the receive loop — not string-parsed, which production never does.
- decode_record: per-mutation app-state decode (AES-CBC + content/index
  HMAC + prost + JSON index), up to ~1000x per resume patch. process_patch
  covered the loop but never isolated this inner per-record cost.
- group out-of-order decrypt worst case: a ~2000-deep skipped-key backlog,
  the full out-of-order decrypt (backlog-sized record clone + signature
  check dominate; the O(n) remove_sender_message_key scan is a smaller
  slice). Baseline, not a scan-isolating microbench.
- process_sender_key_distribution_message: SKDM ingest into a fresh store,
  the first-group-message-per-sender cost, previously only run in setup.

All inputs black_boxed and outputs fully observed (the thin-LTO DCE lesson
from the reporting-token bench); expensive setup stays in with_inputs.
Drafted and adversarially verified via workflow.
@coderabbitai

coderabbitai Bot commented Jun 12, 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

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0296d7ab-170c-499d-aef0-72c0814643a4

📥 Commits

Reviewing files that changed from the base of the PR and between b956722 and 2928bd0.

📒 Files selected for processing (3)
  • wacore/appstate/benches/appstate_benchmark.rs
  • wacore/benches/message_utils_benchmark.rs
  • wacore/libsignal/benches/libsignal_benchmark.rs

📝 Walkthrough

Summary by CodeRabbit

  • Tests
    • Enhanced performance benchmarking for core operations across inbound record processing, message metadata parsing, and cryptographic functions.

Walkthrough

This PR adds three independent benchmark suites to measure critical inbound data path performance: app state record decoding ("star" and "contact" shapes), message metadata parsing (DM, group, status broadcast, self-sent), and libsignal group decryption (worst-case out-of-order backlog plus SKDM ingest). All use Divan parameterization.

Changes

Inbound Data Path Benchmarking

Layer / File(s) Summary
App state record decode benchmark
wacore/appstate/benches/appstate_benchmark.rs
setup_record constructs encoded SyncdRecord test fixtures for "star" and "contact" shapes, and bench_decode_record measures per-shape decode cost. Import list is reformatted for readability.
Message info metadata parsing benchmark
wacore/benches/message_utils_benchmark.rs
msg_info_node builds parameterized <message> stanzas with addressing-mode attributes (PN, LID, status, self-sent). bench_parse_message_info measures parse latency for each addressing mode using marshalled binary input.
Libsignal group and SKDM benchmarks
wacore/libsignal/benches/libsignal_benchmark.rs
setup_group_out_of_order_worst_case pre-encrypts backlog and selects tail ciphertext for worst-case linear scanning, measured by bench_group_out_of_order_decrypt_worst_case. setup_skdm_ingest and bench_process_sender_key_distribution_message measure sender-key distribution message ingestion. Import list is reformatted.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • oxidezap/whatsapp-rust#224: Established libsignal benchmark infrastructure that this PR extends with additional group decryption and SKDM scenarios.
  • oxidezap/whatsapp-rust#828: Migrated benchmark harness to Divan, which provides the parameterization and sampling framework used throughout this PR.

Suggested labels

performance

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding benchmark coverage for four inbound/group hot paths to establish CodSpeed baselines.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, clearly explaining the motivation, what each benchmark covers, and implementation precision details.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bench/inbound-hotpaths

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 and usage tips.

@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.

No issues found across 3 files

Re-trigger cubic

@codspeed-hq

codspeed-hq Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will improve performance by 28.6%

⚡ 2 improved benchmarks
❌ 1 (👁 1) regressed benchmark
✅ 154 untouched benchmarks
🆕 16 new benchmarks

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory bench_group_decrypt_message 2.6 KB 1.6 KB +64.02%
Memory bench_group_encrypt_message 2.4 KB 1.6 KB +49.21%
🆕 Memory bench_decode_record[contact] N/A 385 B N/A
🆕 Memory bench_decode_record[star] N/A 484 B N/A
🆕 Memory bench_parse_message_info[dm_pn] N/A 31 B N/A
🆕 Memory bench_parse_message_info[group_lid] N/A 33 B N/A
🆕 Memory bench_parse_message_info[self_sent] N/A 21 B N/A
🆕 Memory bench_parse_message_info[status_broadcast] N/A 21 B N/A
🆕 Memory bench_group_out_of_order_decrypt_worst_case N/A 126.4 KB N/A
🆕 Memory bench_process_sender_key_distribution_message N/A 2.3 KB N/A
🆕 Simulation bench_decode_record[contact] N/A 40.5 µs N/A
🆕 Simulation bench_decode_record[star] N/A 42.7 µs N/A
🆕 Simulation bench_parse_message_info[dm_pn] N/A 9.1 µs N/A
🆕 Simulation bench_parse_message_info[group_lid] N/A 9.6 µs N/A
🆕 Simulation bench_parse_message_info[self_sent] N/A 8.9 µs N/A
🆕 Simulation bench_parse_message_info[status_broadcast] N/A 9.5 µs N/A
🆕 Simulation bench_group_out_of_order_decrypt_worst_case N/A 651.8 µs N/A
🆕 Simulation bench_process_sender_key_distribution_message N/A 93.7 µs N/A
👁 Simulation bench_decrypt_with_previous_session 5 µs 5.7 µs -13.1%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing bench/inbound-hotpaths (2928bd0) with main (b956722)

Open in CodSpeed

@jlucaso1
jlucaso1 merged commit 53c7975 into main Jun 12, 2026
14 checks passed
@jlucaso1
jlucaso1 deleted the bench/inbound-hotpaths branch June 12, 2026 15:59
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