Skip to content

perf(flow-chat): render recent session history first#958

Merged
limityan merged 1 commit into
GCWing:mainfrom
limityan:yanzhn/startup-session-perf-followup
May 30, 2026
Merged

perf(flow-chat): render recent session history first#958
limityan merged 1 commit into
GCWing:mainfrom
limityan:yanzhn/startup-session-perf-followup

Conversation

@limityan
Copy link
Copy Markdown
Collaborator

@limityan limityan commented May 30, 2026

Summary

  • Restore historical sessions with the latest 3 turns first, then hydrate the full history after a short delay when the session state is still unchanged.
  • Add backend tail-turn loading for restore_session_view so the first historical session open does not read and convert every older turn before showing the latest content.
  • Keep large completed model rounds anchored on their newest groups while preserving head-anchored progressive rendering for streaming rounds.
  • Add a static preload hint while the debug WebView/Vite module graph is still loading, and fix duplicate React keys in restored plan todo rendering.

Related issue: #949

Performance Test Scope

This PR is evaluated from user-facing business scenarios, not only isolated helper speedups. The main target is first open of historical sessions, especially sessions with enough history that reading every turn delays the latest visible conversation. Startup is included because the PR adds a preload hint, but this PR does not claim startup latency improvement.

Test environment and method:

  • Windows desktop debug preview on this branch after rebasing to latest main.
  • Startup/session-list data comes from app and webview startup logs for PR commit d3eec23d.
  • Historical-session restore data uses the same persistence restore path as the app. The baseline column is the no-tail/full restore behavior used before this PR; the PR column is tailTurnCount=3, followed by the existing full restore as delayed background hydration.
  • Local restore benchmark was run after one warm-up, 7 measured repetitions per sample, on the 5 largest local sessions by turn count. Session identifiers are intentionally omitted from this PR body because they are not meaningful review data.

Scenario Results

Business scenario Baseline / reference behavior PR #958 result Product impact
Debug startup to visible native window Existing native show path Main window show at 944 ms after main-window create start No latency win claimed; unsafe delayed-window strategy was removed.
Debug startup to frontend script Existing Vite/WebView cold module path first_script_eval at 9799.4 ms Still slow; preload hint only prevents blank white wait.
Debug startup to shell readiness Existing readiness path interactive_shell_ready at 10557 ms Still a follow-up for #949; not solved by this PR.
Startup workspace/session navigation APIs Existing paged metadata path get_opened_workspaces 15.1 ms, get_recent_workspaces 13.9 ms, 7 list_persisted_sessions_page calls max 14.6 ms Confirms workspace/history list remains visible and responsive after removing delayed-window logic.
First open of small/current session Full restore is effectively unavoidable 1/1 turn restored in 133.4 ms, convert 1.0 ms, state commit 0.5 ms Neutral path; no tail-load benefit when the session has no older history.
First open of larger historical sessions Full history read before first render Tail-3 first restore reads only latest turns, then full history hydrates after 150 ms if state is unchanged Improves time to latest visible conversation, but does not remove full-history cost.
Completed large model round rendering Previously rendered from the oldest visible groups first Completed rounds render newest visible groups first; streaming rounds remain anchored at the beginning Improves perceived latest-content priority; covered by unit tests, no separate browser timing claimed.
Restored plan todo rendering Duplicate IDs could trigger React key warnings Stable duplicate-safe render keys Correctness fix; no performance win claimed.

Historical Session Restore Measurements

The table below shows the tradeoff explicitly: the PR improves the first visible restore by loading tail turns, while the delayed full hydrate still pays the old full restore cost in the background.

Local sample Turns Size Baseline full restore avg PR first restore avg (tail=3) Deferred full hydrate cost still paid Turn files avoided before first render
A 26 3.02 MB 75.5 ms 4.2 ms 75.5 ms 23
B 23 4.29 MB 99.5 ms 5.8 ms 99.5 ms 20
C 17 1.33 MB 35.1 ms 2.4 ms 35.1 ms 14
D 14 2.95 MB 59.3 ms 2.9 ms 59.3 ms 11
E 11 3.80 MB 79.7 ms 10.0 ms 79.7 ms 8

Summary across these 5 samples:

  • Baseline full restore avg range: 35.1-99.5 ms.
  • PR first restore avg range: 2.4-10.0 ms.
  • Average initial backend restore reduction across samples: 69.8 ms to 5.1 ms, about 92.7% lower before first render.
  • Background full hydration still costs 35.1-99.5 ms after the 150 ms delay; this PR changes when the cost is paid, not whether full history eventually exists.

Risks And Mitigations

  • Full history hydration now starts 150 ms after the latest turns are committed. It only applies when the session still contains the same initial tail turn ids, so it should not overwrite a user action or newly appended live turn.
  • Small sessions and already-short histories do not benefit materially; the implementation keeps behavior compatible by reporting isPartial=false and skipping background hydration when all turns are already loaded.
  • The tail restore response includes isPartial, loadedTurnCount, and totalTurnCount; existing UI callers use those fields for hydration and do not rely on the response session.turnCount for metadata. Future callers should use totalTurnCount when requesting a partial view.
  • The static preload hint is intentionally simple and runs before React/i18n initialization. It reduces blank-screen perception in debug preview but does not reduce the remaining interactive_shell_ready time.
  • Remaining startup work, especially WebView/Vite module evaluation and deferred systems such as ACP requirement probing, still needs follow-up optimization in perf(startup): continue reducing desktop startup and interactive shell readiness time #949.

Validation

  • pnpm run fmt:rs
  • pnpm --dir src/web-ui run test:run -- TodoWriteDisplay.test.tsx FlowChatStore.test.ts modelRoundProgressiveRender.test.ts
  • pnpm --dir src/web-ui run test:run -- FlowChatStore.test.ts modelRoundProgressiveRender.test.ts
  • pnpm run type-check:web
  • cargo test -p bitfun-core agentic::persistence::manager::tests::load_session_tail_turns_returns_latest_turns_in_chronological_order -- --nocapture
  • cargo check -p bitfun-core
  • cargo check -p bitfun-desktop (passes with the existing parse_clipboard_path_segments dead_code warning)
  • git diff --check
  • Manual debug preview log check: workspace and session list APIs returned successfully; historical restore used tailTurnCount: 3.
  • CI run 26673380390: Frontend Build and Rust Build Check on macOS, Ubuntu, and Windows all passed.

Load the latest restored turns first, hydrate older history in the background, and keep large completed model rounds anchored on their newest groups. Also adds a static preload hint for debug WebView cold start and fixes duplicate todo keys in restored plan displays.
@limityan limityan marked this pull request as ready for review May 30, 2026 03:57
@limityan limityan merged commit 1e333ec into GCWing:main May 30, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant