Skip to content

perf(send): trim group-send warm-path CPU and cold fan-out allocations - #936

Merged
jlucaso1 merged 3 commits into
mainfrom
perf/group-send-warm-path
Jul 1, 2026
Merged

perf(send): trim group-send warm-path CPU and cold fan-out allocations#936
jlucaso1 merged 3 commits into
mainfrom
perf/group-send-warm-path

Conversation

@jlucaso1

@jlucaso1 jlucaso1 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Three self-contained optimizations to the group send path, found by profiling an 802-member LID group send. Behavior is unchanged: cargo test -p wacore --lib send:: is green (95 tests) and a full group-send scenario keeps no sender key at 0.

1. Trim the chain lock to the crypto sections

prepare_group_stanza held the per-(group, sender) sender-key lock across the whole function. The lock must span SKDM creation, the pairwise SKDM fan-out and the skmsg encrypt: the first and last touch the sender-key chain atomically, and the fan-out mutates shared per-device Signal sessions that the group path (unlike the DM path) does not lock. Plaintext padding is chain-independent though, so it now runs before the lock, and the guard drops before the stanza build and marshalling instead of being held for the rest of the function.

2. Skip the warm SKDM device scan when nothing changed

filter_skdm_targets is O(devices) per send (three hash lookups per member; ~24M lookups over a 10k-send run to an 802-member group). Memoize the last (resolved-devices, sender-key-device-map) Arc pair that produced an empty needs_skdm; a repeat send observing the same two Arcs is still fully warm and skips the scan. Weak pointers keep the comparison ABA-safe (same contract as GroupDevicesMemo), and either Arc swaps the moment warm state or membership changes, so a stale skip is impossible. Gated on the device memo.

3. Chunk the cold SKDM fan-out

The fan-out spawned one task + oneshot channel + two store clone_box()es per recipient device, so an 800-member group allocated on the order of 5x800 times per cold send (dhat: 123 MB / 45.7k blocks). Encrypt in index-partitioned chunks bounded by ENCRYPT_FANOUT_CONCURRENCY instead: one task per chunk clones the Arc-backed stores once and encrypts its slice sequentially, so ratchet advances still persist while spawns and clones drop to the concurrency limit and parallelism is unchanged. Also fixes a divide-by-zero on an empty device set. Covered by new tests: full multi-chunk fan-out, a sessionless device being skipped, and the empty device set.

Measured (802-member cold send): encrypt fan-out allocation 123 MB to 28.8 MB, blocks 45.7k to 4.1k; dhat allocation peak 107 MB to 49 MB.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

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: db2e416f-b73d-40a2-bed9-fcd1249a7805

📥 Commits

Reviewing files that changed from the base of the PR and between b2ea28b and a27e43d.

📒 Files selected for processing (2)
  • wacore/src/send/encrypt.rs
  • wacore/src/send/tests.rs

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Improved warm-send handling for group messages, reducing unnecessary work on repeated sends.
  • Bug Fixes

    • Improved device fan-out encryption efficiency by processing devices in chunks, while maintaining partial success behavior.
    • Improved group message encryption flow by computing/padding plaintext earlier and tightening the lock scope.
  • Tests

    • Added regression coverage for multi-device encryption, missing-session handling, and empty-device sends.

Walkthrough

Adds a warm memo for repeated empty SKDM resolution, switches multi-device encryption to chunked fan-out, and moves group stanza locking so SKDM creation and SKMSG encryption occur under the sender-key chain lock.

Changes

Send path updates

Layer / File(s) Summary
SKDM warm memoization
src/client.rs, src/client/lifecycle.rs, src/send/mod.rs
Adds and initializes skdm_warm_memo, then uses it to skip filter_skdm_targets when the same resolved-device and sender-key map inputs repeat with an empty result.
Chunked encryption and group lock scope
wacore/src/send/encrypt.rs, wacore/src/send/group.rs, wacore/src/send/tests.rs
Spawns encryption work per chunk instead of per device, updates chunk result aggregation and cancellation logging, adjusts group stanza plaintext/lock timing, and adds raw fan-out tests for full-session, partial-session, and empty-device cases.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested labels: performance

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: performance work on group-send warm-path CPU and cold fan-out allocations.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the three optimizations and their reported effects.
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/group-send-warm-path

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.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84891260e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread wacore/src/send/encrypt.rs Outdated
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

📦 Binary size report

Metric main PR Δ
bin size (stripped) 10.11 MiB 10.13 MiB +17.09 KiB (+0.17%) 🔺
bin .text 8.17 MiB 8.18 MiB +16.69 KiB (+0.20%) 🔺
bin allocated (text+data+bss) 10.11 MiB 10.13 MiB +16.05 KiB (+0.16%) 🔺
llvm-lines wacore 644,791 645,750 +959 (+0.15%) 🔺
llvm-lines wacore copies 17,880 17,926 +46 (+0.26%) 🔺
llvm-lines whatsapp-rust lib 658,630 662,695 +4,065 (+0.62%) 🔺
llvm-lines whatsapp-rust lib copies 20,452 20,615 +163 (+0.80%) 🔺
deps crates (Cargo.lock) 467 467 0
.text per crate
Crate main PR Δ
.text whatsapp_rust 1.49 MiB 1.50 MiB +12.44 KiB (+0.82%) 🔺
.text wacore 530.62 KiB 533.61 KiB +3.00 KiB (+0.56%) 🔺
.text wacore_binary 157.79 KiB 157.79 KiB 0
.text wacore_libsignal 165.86 KiB 165.86 KiB 0
.text wacore_appstate 144.24 KiB 144.24 KiB 0
.text wacore_noise 27.71 KiB 27.71 KiB 0
.text waproto 871.99 KiB 871.99 KiB 0
.text whatsapp_rust_sqlite_storage 475.72 KiB 475.72 KiB 0
.text whatsapp_rust_tokio_transport 43.57 KiB 43.57 KiB 0
.text whatsapp_rust_ureq_http_client 8.81 KiB 8.81 KiB 0
.text std 998.17 KiB 999.40 KiB +1.23 KiB (+0.12%) 🔺
.text other deps 3.28 MiB 3.28 MiB 0
Top movers (cargo-bloat attribution)
Crate main PR Δ
whatsapp_rust 1.49 MiB 1.50 MiB +12.44 KiB (+0.82%)
wacore 530.62 KiB 533.61 KiB +3.00 KiB (+0.56%)
std 998.17 KiB 999.40 KiB +1.23 KiB (+0.12%)

Baseline: 421c66a3b (latest main run) · Head: 58d27fac6 · Graphs

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
wacore/src/send/group.rs (1)

384-430: 🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

Don’t hold the sender-key chain lock during SKDM fan-out.

The guard is acquired before encrypt_for_devices_with_sessions(...).await, so a cold large-group send holds the per-chain mutex while doing pairwise device encryption. That work is chain-independent after create_sender_key_distribution_message_for_group returns, and it serializes same-group sends longer than the “ratchet steps” comment claims.

🔒 Suggested shape for narrowing the critical section
-    let chain_lock = stores
-        .sender_key_store
-        .sender_key_lock(&sender_key_name)
-        .await;
-    let chain_guard = chain_lock.lock().await;
+    let chain_lock = stores
+        .sender_key_store
+        .sender_key_lock(&sender_key_name)
+        .await;
 
+    let mut axolotl_skdm_bytes = None;
+    let skmsg = {
+        let chain_guard = chain_lock.lock().await;
+        if distribution_list.is_some() {
+            axolotl_skdm_bytes = Some(
+                create_sender_key_distribution_message_for_group(
+                    stores.sender_key_store,
+                    &sender_key_name,
+                )
+                .await?,
+            );
+        }
+        let skmsg = encrypt_group_message(
+            stores.sender_key_store,
+            &sender_key_name,
+            &plaintext,
+            &mut rand::make_rng::<rand::rngs::StdRng>(),
+        )
+        .await?;
+        drop(chain_guard);
+        skmsg
+    };
+
     if let Some(ref distribution_list) = distribution_list {
-        let axolotl_skdm_bytes = create_sender_key_distribution_message_for_group(
-            stores.sender_key_store,
-            &sender_key_name,
-        )
-        .await?;
+        let Some(axolotl_skdm_bytes) = axolotl_skdm_bytes else {
+            unreachable!("SKDM bytes are created whenever distribution_list is present");
+        };
 
         if let Some(plan) = session_plan {
             let skdm_wrapper_msg = wa::Message {

Also applies to: 474-485

🤖 Prompt for 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.

In `@wacore/src/send/group.rs` around lines 384 - 430, The sender-key chain lock
in send_group is held too long because it remains active through
encrypt_for_devices_with_sessions, which serializes cold large-group sends
unnecessarily. Narrow the critical section in send/group.rs by keeping the lock
only around create_sender_key_distribution_message_for_group and any chain-state
updates, then release it before SKDM fan-out and device encryption; use the
existing sender_key_lock and chain_guard flow as the anchor for the refactor.
Apply the same lock-scope reduction to the matching later block referenced in
the diff so the SKDM and main message paths both avoid holding the per-chain
mutex across chain-independent work.
🤖 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 `@wacore/src/send/encrypt.rs`:
- Around line 730-736: The fan-out partitioning in encrypt.rs does not reliably
preserve ENCRYPT_FANOUT_CONCURRENCY because using div_ceil with step_by can
yield too few chunks for totals just above the limit. Update the chunking logic
in the device fan-out loop around total, num_chunks, and in_flight to partition
by chunk index instead of stepping by chunk_size, so the work is split into
exactly num_chunks slices and the intended parallelism is maintained.

---

Outside diff comments:
In `@wacore/src/send/group.rs`:
- Around line 384-430: The sender-key chain lock in send_group is held too long
because it remains active through encrypt_for_devices_with_sessions, which
serializes cold large-group sends unnecessarily. Narrow the critical section in
send/group.rs by keeping the lock only around
create_sender_key_distribution_message_for_group and any chain-state updates,
then release it before SKDM fan-out and device encryption; use the existing
sender_key_lock and chain_guard flow as the anchor for the refactor. Apply the
same lock-scope reduction to the matching later block referenced in the diff so
the SKDM and main message paths both avoid holding the per-chain mutex across
chain-independent work.
🪄 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: 69e31442-95d6-4a28-985f-5ab443f202b4

📥 Commits

Reviewing files that changed from the base of the PR and between 421c66a and 8489126.

📒 Files selected for processing (5)
  • src/client.rs
  • src/client/lifecycle.rs
  • src/send/mod.rs
  • wacore/src/send/encrypt.rs
  • wacore/src/send/group.rs

Comment thread wacore/src/send/encrypt.rs Outdated
@codspeed-hq

codspeed-hq Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 179 untouched benchmarks


Comparing perf/group-send-warm-path (a27e43d) with main (421c66a)

Open in CodSpeed

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

3 issues found across 5 files

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

Re-trigger cubic

Comment thread wacore/src/send/encrypt.rs Outdated
Comment thread wacore/src/send/encrypt.rs Outdated
Comment thread wacore/src/send/encrypt.rs Outdated
@jlucaso1
jlucaso1 force-pushed the perf/group-send-warm-path branch 2 times, most recently from 013adce to 5f4c159 Compare July 1, 2026 20:49

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
wacore/src/send/tests.rs (1)

3482-3491: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

This doc comment is now attached to the wrong test — that's sloppy, let's fix it.

The comment at Lines 3482-3485 describes reporting a replaced identity via the resolver, but you inserted the new empty-device-set test right underneath it. In Rust doc comments bind to the next item, so this now documents encrypt_for_devices_with_sessions_raw_handles_empty_device_set — which has nothing to do with replaced identities. Meanwhile encrypt_for_devices_reports_replaced_identity at Line 3524 lost its description entirely. Move it so each comment sits above the test it actually explains. Things need to be right.

🧹 Proposed fix: move the comment back to its test
-    /// The send path must report a replaced identity via the resolver when
-    /// establishing a session whose bundle carries a new identity key for an
-    /// address we already knew (peer reinstall). Mirrors WA Web saveIdentity
-    /// -> handleNewIdentity firing during outbound session setup.
     /// Regression (PR `#936` review): the chunked encrypt fan-out must return an
     /// empty result — not divide by zero — when the device set is empty. This is
     /// reachable on the cold force-SKDM path once the sender/hosted devices are
     /// filtered out, and the previous per-device fan-out returned empty here.
     #[tokio::test]
     async fn encrypt_for_devices_with_sessions_raw_handles_empty_device_set() {

Then re-add the replaced-identity comment above encrypt_for_devices_reports_replaced_identity at Line 3524:

+    /// The send path must report a replaced identity via the resolver when
+    /// establishing a session whose bundle carries a new identity key for an
+    /// address we already knew (peer reinstall). Mirrors WA Web saveIdentity
+    /// -> handleNewIdentity firing during outbound session setup.
     #[tokio::test]
     async fn encrypt_for_devices_reports_replaced_identity() {
🤖 Prompt for 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.

In `@wacore/src/send/tests.rs` around lines 3482 - 3491, The doc comment
describing the replaced-identity resolver behavior is attached to the wrong
test, so move that comment from
encrypt_for_devices_with_sessions_raw_handles_empty_device_set to the test it
actually documents, encrypt_for_devices_reports_replaced_identity. Keep the
empty-device-set test with only the regression comment that matches its
behavior, and restore the replaced-identity description immediately above
encrypt_for_devices_reports_replaced_identity so Rust doc binding is correct.
🤖 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.

Outside diff comments:
In `@wacore/src/send/tests.rs`:
- Around line 3482-3491: The doc comment describing the replaced-identity
resolver behavior is attached to the wrong test, so move that comment from
encrypt_for_devices_with_sessions_raw_handles_empty_device_set to the test it
actually documents, encrypt_for_devices_reports_replaced_identity. Keep the
empty-device-set test with only the regression comment that matches its
behavior, and restore the replaced-identity description immediately above
encrypt_for_devices_reports_replaced_identity so Rust doc binding is correct.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ddcc4d59-94e8-4cf0-a5fd-53d0a202447f

📥 Commits

Reviewing files that changed from the base of the PR and between 8489126 and 013adce.

📒 Files selected for processing (2)
  • wacore/src/send/encrypt.rs
  • wacore/src/send/tests.rs

@jlucaso1
jlucaso1 force-pushed the perf/group-send-warm-path branch from 5f4c159 to 44a1f97 Compare July 1, 2026 20:52

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
wacore/src/send/group.rs (1)

383-428: 🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

Don’t hold the sender-key chain lock during pairwise SKDM fan-out.

chain_guard currently spans encrypt_for_devices_with_sessions, so a large cold group send keeps same-group sends blocked while pairwise device encryption runs. Keep only SKDM creation + encrypt_group_message under the lock, then drop before fan-out/stanza assembly.

Also applies to: 480-482

🤖 Prompt for 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.

In `@wacore/src/send/group.rs` around lines 383 - 428, The sender-key chain lock
is held too long in group send flow, blocking other same-group sends during
pairwise SKDM fan-out. Keep `chain_guard` only around sender-key record creation
and `encrypt_group_message`/SKDM preparation in `send/group.rs`, then release it
before calling `encrypt_for_devices_with_sessions` and stanza assembly. Adjust
the scope near `sender_key_lock`,
`create_sender_key_distribution_message_for_group`, and the matching SKDM/send
path referenced in the later block so fan-out runs without the chain lock held.
🤖 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.

Outside diff comments:
In `@wacore/src/send/group.rs`:
- Around line 383-428: The sender-key chain lock is held too long in group send
flow, blocking other same-group sends during pairwise SKDM fan-out. Keep
`chain_guard` only around sender-key record creation and
`encrypt_group_message`/SKDM preparation in `send/group.rs`, then release it
before calling `encrypt_for_devices_with_sessions` and stanza assembly. Adjust
the scope near `sender_key_lock`,
`create_sender_key_distribution_message_for_group`, and the matching SKDM/send
path referenced in the later block so fan-out runs without the chain lock held.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ecc65f00-3ba1-48a5-968a-09dcc142bad2

📥 Commits

Reviewing files that changed from the base of the PR and between 013adce and 44a1f97.

📒 Files selected for processing (6)
  • src/client.rs
  • src/client/lifecycle.rs
  • src/send/mod.rs
  • wacore/src/send/encrypt.rs
  • wacore/src/send/group.rs
  • wacore/src/send/tests.rs

@jlucaso1
jlucaso1 force-pushed the perf/group-send-warm-path branch 2 times, most recently from 9dfbd27 to c8179d3 Compare July 1, 2026 21:12

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c8179d3b78

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread wacore/src/send/group.rs Outdated
jlucaso1 added 2 commits July 1, 2026 18:46
The per-(group,sender) sender-key lock must span SKDM creation, the pairwise
SKDM fan-out and the skmsg encrypt: the first and last touch the sender-key
chain atomically, and the fan-out mutates shared per-device Signal sessions
that the group path (unlike the DM path) does not lock. Plaintext padding is
chain-independent though, so compute it before taking the lock, and drop the
guard before the stanza build and marshalling instead of holding it for the
rest of the function.
filter_skdm_targets is O(devices) per send (three hash lookups per member),
which dominates warm group sends to large groups. Memoize the last
(resolved-devices, sender-key-device-map) Arc pair that produced an empty
needs_skdm; a repeat send observing the same two Arcs is still fully warm and
skips the scan. Weak pointers keep the comparison ABA-safe, and either Arc
swaps the moment warm state or membership changes, so a stale skip is
impossible. Gated on the device memo (otherwise the device Arc is rebuilt each
call and the check can never hit).
@jlucaso1
jlucaso1 force-pushed the perf/group-send-warm-path branch from c8179d3 to b2ea28b Compare July 1, 2026 21:46

@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 `@wacore/src/send/group.rs`:
- Around line 383-388: The sender-key chain lock in the group send path only
serializes by sender-key name and does not cover cross-group Signal session
fan-out, so concurrent cold sends can still race the per-device ratchet. Update
the group send flow around the SKDM fan-out in the send/group.rs logic to
acquire the same per-device session lock mechanism used by the DM path, either
by reusing session_locks directly or by threading a lock provider into this
layer, and keep the SKDM creation, fan-out, and encrypt steps under that
serialization.
🪄 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: 031bbdfd-4c86-43fe-b6a2-27a8389a2d4a

📥 Commits

Reviewing files that changed from the base of the PR and between 44a1f97 and b2ea28b.

📒 Files selected for processing (6)
  • src/client.rs
  • src/client/lifecycle.rs
  • src/send/mod.rs
  • wacore/src/send/encrypt.rs
  • wacore/src/send/group.rs
  • wacore/src/send/tests.rs

Comment thread wacore/src/send/group.rs
The fan-out spawned one task + oneshot channel + two store clone_box()es per
recipient device, so an 800-member group allocated on the order of 5x800 times
per cold send. Encrypt in index-partitioned chunks instead (bounded by
ENCRYPT_FANOUT_CONCURRENCY): one task per chunk clones the Arc-backed stores
once and encrypts its slice sequentially, so ratchet advances still persist,
spawns and clones drop to the concurrency limit, and parallelism is unchanged.
Also fixes a divide-by-zero on an empty device set. Covered by new tests for
the full fan-out (multi-chunk), a sessionless device being skipped, and the
empty device set. Wire order is irrelevant (phash sorts before hashing on both
ends).
@jlucaso1
jlucaso1 force-pushed the perf/group-send-warm-path branch from b2ea28b to a27e43d Compare July 1, 2026 21:51
@jlucaso1
jlucaso1 merged commit 20c7718 into main Jul 1, 2026
14 checks passed
@jlucaso1
jlucaso1 deleted the perf/group-send-warm-path branch July 1, 2026 22:00
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