Skip to content

perf(acp): avoid repeated observer batch serialization - #9483

Merged
sanket1729 merged 1 commit into
mainfrom
sanketk/observer-frame-packing
Nov 14, 2026
Merged

sanket1729 merged 1 commit into
mainfrom
sanketk/observer-frame-packing

Conversation

@sanket1729

Copy link
Copy Markdown
Contributor

Replaces #9413 with the packing optimization refreshed against main on a branch in this repository.

Summary

Busy agent activity streams repeatedly build and serialize a growing JSON batch just to check whether the next event fits. Reuse cached event sizes, measure the newest outer envelope, and build the batch payload once per completed frame.

Preserve the wire format, greedy packing, per-channel order, channel barriers, byte budget, and one-frame-per-second relay cadence. Exact-limit coverage checks escaping, UTF-8, optional metadata, and array separators. Move the queue tests into a separate module to satisfy the file-size rule; their test names stay unchanged.

Related issue

Related to #7987. This builds on the merged fitting/locking work in #9381 and retention limits in #9436. Closest earlier batching work: #4917. No duplicate packing fix found among open PRs.

Testing

The ignored probe fills the production queue before timing, drains every event, and checks complete FIFO delivery, frame byte limits, and empty byte accounting.

CARGO_INCREMENTAL=0 CARGO_PROFILE_RELEASE_LTO=thin CARGO_PROFILE_RELEASE_CODEGEN_UNITS=4 \
  cargo test --release -p buzz-acp --lib observer::packing_tests::publish_queue_drain_probe -- \
  --exact --ignored --nocapture

BUZZ_OBSERVER_PROBE_EVENTS=100 cargo test --release -p buzz-acp --lib \
  observer::packing_tests::publish_queue_drain_probe -- --exact --ignored --nocapture

Five alternating fresh release processes per arm and workload compared baseline 59ae028a3 with candidate 237b928b9 on macOS arm64, Rust 1.98.1. Both arms used opt-level=3, thin LTO and four codegen units, with incremental compilation and compiler-cache wrappers off. Each executable was rebuilt separately and its probe identity verified. Medians:

Events Before After Frames in both arms
100 6.760 ms 0.108 ms 1
10,000 1,597.509 ms 7.844 ms 30

The one-event control measured 2.04 → 2.21 microseconds. The timed region covers packing only; ingestion, validation, encryption, publish pacing, relay delivery, and rendering are excluded. These local results do not establish an overall app latency improvement. No timing threshold was added to CI.

Native and deployed-relay latency, independent review, and human verification remain pending. Keep this PR in draft.

Generated with AI assistance

Reuse cached event sizes when packing observer frames. Measure only the outer envelope for each candidate and build the payload once per completed batch.

Co-authored-by: Codex <[email protected]>
Signed-off-by: Sanket Kanjalkar <[email protected]>
@sanket1729
sanket1729 marked this pull request as ready for review November 13, 2026 21:57
@sanket1729
sanket1729 requested a review from a team as a code owner November 13, 2026 21:57
@sanket1729
sanket1729 deployed to codex-review November 13, 2026 21:58 — with GitHub Actions Active
@github-actions github-actions Bot added the codex-security-review-current The posted Codex security review matches its recorded range. label Nov 13, 2026
@github-actions

Copy link
Copy Markdown

🔐 Codex Security Review

Note: This is an automated, security-focused review generated by Codex.
Use it as a supplement to human review; false positives are possible.

Scope

  • Exact PR diff: b6db61faa0fcb467ce523e1bacae917f1f588fb9...237b928b9cd2563c6ccc4d69b2c1052543708753
  • Model: gpt-6.1-sol

💡 Click "edited" above to see earlier reviews for this PR.


Review Summary

Overall Risk: NONE

No concrete security, correctness, or reliability findings in the authorized PR range. Cached byte accounting matches the batch serialization format, and channel boundaries, ordering, and frame limits remain preserved.

Findings

No concrete security, correctness, or reliability findings were identified.

Notes

  • Review used read-only source and history inspection. Builds and tests were not executed, as instructed.

Generated by Codex Security Review |
Requested by: @sanket1729 |
Workflow run

@joahg joahg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 No blocking findings. I checked the new packing math against the old one, and it is equivalent. The old code serialized the whole envelope after pushing event N, with the envelope metadata taken from that newest event. The new code measures empty_batch_envelope(&event) (that metadata plus the [] brackets), adds the cached post-fit event sizes, and adds one comma per preceding event. That is the same byte count. The first event is always taken, so a single oversized event still ships unwrapped. The overflow event goes back to the head of its channel's queue, pending_bytes only drops for picked events, and channel barriers and FIFO order are unchanged. The cached sizes cannot go stale, because queued events are only mutated inside fit_observer_event_to_budget before the size is recorded, and that function returns the exact serialized length on every path. The exact-limit test uses an independent wire oracle (escaping, UTF-8, optional metadata, commas) at limit -1, 0 and +1, so it covers the packing boundary. The ignored probe is manual only, with no CI timing gate, which fits the PR's claims. The test move looks mechanical; the CI checks are green.

Optional: the PR body says to keep it in draft pending native and relay latency checks and human verification, but it is currently marked ready.

I did not run the tests or the probe locally, and I did not re-diff every moved test line for exactness.

// Add cached event sizes and one comma per preceding event;
// only the newest event's envelope metadata needs measuring.
if !picked.is_empty()
&& serialized_len(&empty_batch_envelope(&event))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Optional: serialized_len returns usize::MAX on a serialization error, and this sum now adds to it. The old code only compared against it. That can't realistically fail for a string-and-[] envelope, but saturating_add would keep the old fail-closed behavior at no cost.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

sure, i can make this saturing_add . does not hurt adding it

@kazemek21 kazemek21 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Kyle reviewed this PR and the Nexus review-tracker notes and approved with no comments.

Posted by Codex (gpt-6.1-sol) on behalf of kylez

@sanket1729
sanket1729 merged commit 5780bd7 into main Nov 14, 2026
97 checks passed
@sanket1729
sanket1729 deleted the sanketk/observer-frame-packing branch November 14, 2026 01:39
bostonaholic added a commit that referenced this pull request Nov 14, 2026
…eaction-recipients

* origin/main: (111 commits)
  perf(acp): avoid repeated observer batch serialization (#9483)
  docs(readme): point desktop readers at block/buzz-app and describe where each client lives (#9493)
  test(cli,db): freeze the assertion test clock and give pool release tests a test-lane acquire budget (#9442)
  test(desktop): unmount every TerminalSubstrate tree before the window closes (#9440)
  fix(mobile): drop the iOS share extension from the build until it's signed (#9489)
  chore(release): release Buzz Desktop version 0.5.30 (#9491)
  perf(mobile): parse each event's thread reference once (#9460)
  perf(mobile): load only the directory when search opens (#9466)
  perf(mobile): stop rebuilding Home's channel list when a route covers it (#9459)
  perf(mobile): ask typing subscriptions only for the typing window (#9454)
  perf(mobile): skip avatar URL parsing for non-HTTP URLs (#9448)
  perf(mobile): download the identity archive list only when it changed (#9445)
  perf(mobile): don't treat a Control Center pull as a resume (#9443)
  fix(mobile): keep a superseded roster read out of the offline snapshot (#9452)
  perf(mobile): read channel bot roles from the member list (#9451)
  perf(mobile): read Activity once per reconnect (#9455)
  fix(mobile): offer role controls for agents (#9475)
  perf(mobile): stop rebuilding the native nav bar on every scrolled frame (#9458)
  perf(mobile): keep verified-name batches open as people are added (#9450)
  perf(mobile): read only changed custom emoji sets on reconnect (#9446)
  ...

Signed-off-by: Matthew Boston <[email protected]>

This branch was successfully deployed

1 active deployment
codex-review — 237b928b Deployed Nov 13, 2026 by sanket1729 via Run Codex Security Review #15095
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex-security-review-current The posted Codex security review matches its recorded range.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants