Skip to content

perf: request-path hot-path optimizations — Tier 3–4 (#149) - #182

Merged
amondnet merged 8 commits into
mainfrom
amondnet/perf-2
Jul 16, 2026
Merged

perf: request-path hot-path optimizations — Tier 3–4 (#149)#182
amondnet merged 8 commits into
mainfrom
amondnet/perf-2

Conversation

@amondnet

@amondnet amondnet commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Tier 3–4 of the request-path hot-path performance audit (#149). Four sub-issues, one commit each:

Notes

  • The codex_ws select! polls the frame source before the idle timer (biased) to preserve the inner-future-first semantics of the tokio::time::timeout it replaces — a frame arriving as the deadline elapses is delivered, not dropped in favor of the timeout.

Testing

Docs

Internal performance refactors only — no change to observable behavior, config keys, endpoints, CLI, or provider/model semantics, so no README.md / docs/ / site/ update is required (per AGENTS.md).

Closes #156
Closes #158
Closes #159
Closes #160
Part of #149


Summary by cubic

Speeds up the request path by reducing pool lock scope and per-account work, allowing concurrent credential resolution for valid ChatGPT tokens, and trimming Codex WS idle-timer overhead. No behavior changes — just faster hot paths.

  • Refactors

    • Account selection: hold the entries mutex only for insertion/expiry/snapshot; run quota assessment and weekly reset after unlock. Compute is_fable_model once per selection; provider string hoisted. QuotaState is Clone; assess_quota/governing_weekly_reset take a precomputed bool.
    • Auth: resolve_or_cooldown skips the per-account refresh lock for valid tokens; expired-token refresh remains single-flighted in CodexAuthStore::get_valid_chatgpt. Tests ensure valid-token resolution doesn’t wait.
    • WS: run_turn reuses a pinned tokio::time::Sleep and uses biased select so frames at the deadline are delivered. BoundaryTracker::push bulk-copies only the trailing 4 bytes. Tests cover idle-timeout error surfacing and long-chunk/empty/3-byte boundary cases.
  • Bug Fixes

    • Removed a flaky idle-timer reset test; kept the reliable timeout-after-silence coverage.

Written for commit 3c8cb57. Summary will update on new commits.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request optimizes account credential resolution by removing the per-account refresh lock, relying instead on the auth store's internal single-flighting. It also refactors quota assessment to pass QuotaState directly, optimizes boundary tracking in keepalive streams, and improves websocket idle timeout handling using a pinned sleep timer with a biased select. The reviewer suggested a medium-severity optimization in src/accounts.rs to avoid redundant quota evaluations and heap allocations for duplicate account aliases by querying only unique representatives.

Comment thread src/accounts.rs
@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.89503% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/adapters/responses/codex_ws.rs 96.36% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 11 untouched benchmarks


Comparing amondnet/perf-2 (3c8cb57) with main (2039c27)

Open in CodSpeed

amondnet added 2 commits July 16, 2026 20:29
Close the two coverage gaps surfaced while reviewing PR #182:
- codex_ws run_turn: turn-level 300s idle timeout surfaces a transport
  error (paused-time test) — exercises the reused pinned Sleep + biased select.
- keepalive BoundaryTracker::push: empty-chunk early return and the
  retained=3 copy_within offset (old-tail byte retention).
@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown

Greptile Summary

This PR delivers Tier 3–4 hot-path optimizations to the request path: locking scope in AccountPool::select_order_inner is narrowed so quota assessment runs after the entries mutex is released (on a cloned snapshot), is_fable_model and the provider string are computed once per selection, resolve_or_cooldown drops its per-account pool lock for valid tokens, and the Codex WS run_turn reuses a single pinned Sleep via a biased select! while BoundaryTracker::push is rewritten to bulk-copy only the trailing 4 bytes.

Confidence Score: 5/5

All four hot-path changes are safe to merge: the quota-assessment refactor operates on a well-formed clone taken after expiry, the lock removal in resolve_or_cooldown is backed by auth-layer single-flighting and a direct regression test, the pinned idle timer preserves frame-over-deadline delivery via biased polling, and BoundaryTracker's bulk-copy path is verified correct for every sub-tail length (0, 1, 2, 3, ≥4) by the new unit tests.

The quota assessment now runs on a cloned QuotaState after the entries mutex is released — expire_stale_quota still mutates under the lock, so the clone captures post-expiry state and the pure computation outside the lock is safe. The lock removal from resolve_or_cooldown is correct because CodexAuthStore::get_valid_chatgpt serializes refreshes internally per credential path; the new test validates that a held pool lock doesn't block valid-token resolution. The biased select! + pinned Sleep is a drop-in replacement for tokio::time::timeout with stronger frame-wins-at-deadline semantics. BoundaryTracker::push was verified manually and by tests for all retained lengths including the overlap case handled correctly by copy_within's memmove semantics.

No files require special attention.

Important Files Changed

Filename Overview
src/accounts.rs Quota assessment lifted out of the entries mutex via QuotaState clone; is_fable_model and provider string hoisted once per selection. Logic is equivalent and correctness is maintained by the clone-then-assess pattern.
src/adapters/responses/pool.rs Per-account pool refresh lock removed from resolve_or_cooldown; valid-token path is now lock-free and a regression test verifies it doesn't block on the held pool lock. force_refresh_or_cooldown retains its per-account lock.
src/adapters/responses/codex_ws.rs Idle timer changed from a per-frame tokio::time::timeout to a single pinned Sleep with biased select!; reset happens unconditionally before each frame wait. New test covers the silence-to-timeout path with paused time and real loopback I/O.
src/keepalive.rs BoundaryTracker::push rewritten from O(N) rotate-per-byte to O(1) bulk copy of trailing 4 bytes. Empty-chunk early return prevents a no-op copy_within. New tests cover long chunk, empty push, and 3-byte split edge cases.
src/adapters/responses/inbound.rs Comment-only update to forward_codex_passthrough reflecting the lock-removal in resolve_or_cooldown.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller
    participant Pool as AccountPool
    participant Lock as entries Mutex
    participant Quota as assess_quota (pure)

    Note over Caller,Quota: Before (all under lock)
    Caller->>Lock: acquire
    Lock->>Pool: expire_stale_quota
    Lock->>Quota: assess_quota (holding lock)
    Lock->>Quota: governing_weekly_reset (holding lock)
    Lock-->>Caller: release

    Note over Caller,Quota: After (quota assessment outside lock)
    Caller->>Lock: acquire
    Lock->>Pool: expire_stale_quota
    Lock->>Pool: quota.clone()
    Lock-->>Caller: release (lock dropped earlier)
    Caller->>Quota: assess_quota(cloned_quota)
    Caller->>Quota: governing_weekly_reset(cloned_quota)

    Note over Caller,Quota: resolve_or_cooldown valid token path (Before)
    Caller->>Pool: refresh_lock.lock().await
    Pool->>Pool: resolve_chatgpt_account
    Pool-->>Caller: Credential (lock released)

    Note over Caller,Quota: resolve_or_cooldown valid token path (After)
    Caller->>Pool: resolve_chatgpt_account (no pool lock)
    Pool-->>Caller: Credential (concurrent safe)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Caller
    participant Pool as AccountPool
    participant Lock as entries Mutex
    participant Quota as assess_quota (pure)

    Note over Caller,Quota: Before (all under lock)
    Caller->>Lock: acquire
    Lock->>Pool: expire_stale_quota
    Lock->>Quota: assess_quota (holding lock)
    Lock->>Quota: governing_weekly_reset (holding lock)
    Lock-->>Caller: release

    Note over Caller,Quota: After (quota assessment outside lock)
    Caller->>Lock: acquire
    Lock->>Pool: expire_stale_quota
    Lock->>Pool: quota.clone()
    Lock-->>Caller: release (lock dropped earlier)
    Caller->>Quota: assess_quota(cloned_quota)
    Caller->>Quota: governing_weekly_reset(cloned_quota)

    Note over Caller,Quota: resolve_or_cooldown valid token path (Before)
    Caller->>Pool: refresh_lock.lock().await
    Pool->>Pool: resolve_chatgpt_account
    Pool-->>Caller: Credential (lock released)

    Note over Caller,Quota: resolve_or_cooldown valid token path (After)
    Caller->>Pool: resolve_chatgpt_account (no pool lock)
    Pool-->>Caller: Credential (concurrent safe)
Loading

Reviews (4): Last reviewed commit: "test(perf): remove flaky idle-timer rese..." | Re-trigger Greptile

Comment thread src/adapters/responses/codex_ws.rs
amondnet added 3 commits July 16, 2026 20:58
greptile #182: the existing idle-timeout test only proved timeout-after-
silence. Add a paused-time test that delivers a frame just before the
deadline and confirms the reset gives a fresh full window (no premature
timeout), then times out after renewed silence — pinning the reset-after-
activity semantics and biased tie-breaking. Also resume real time during
loopback handshake in both paused-time tests so a fully paused runtime
cannot auto-advance to the idle timer before the first frame arrives.
turn_idle_timer_resets_after_each_frame raced the idle timer under CI
load: a 1s margin before the original deadline was smaller than the
real-time loopback handshake drift, so advancing could cross the initial
sleep(IDLE_TIMEOUT) deadline before run_turn re-armed after frame 1.
Widen the margin to 30s (>> handshake drift) and add a third frame whose
receipt proves run_turn looped and re-armed past the original deadline
before the test crosses it. Test-only; 20x consecutive local passes.
turn_idle_timer_resets_after_each_frame is not deterministic at this
integration layer: proving reset-after-activity requires interleaving
paused-clock fast-forward with real mid-stream socket I/O, and tokio's
paused runtime auto-advances to the next timer whenever both the test
and run_turn park waiting on that I/O — firing the idle timeout before
the mid-stream frame is delivered. It passed locally (fast I/O) but
raced under CI load. Keep the reliable timeout-after-silence test
(turn_idle_timeout_surfaces_transport_error); defer reset-after-activity
coverage to a follow-up that drives run_turn with a mock frame source
instead of a real socket.
@sonarqubecloud

Copy link
Copy Markdown

@amondnet
amondnet merged commit 914f4dd into main Jul 16, 2026
16 checks passed
@amondnet
amondnet deleted the amondnet/perf-2 branch July 16, 2026 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant