Skip to content

perf(mobile): pause elapsed-time timers on hidden thread screens - #15397

Draft
juliusmarminge wants to merge 1 commit into
t3code/mobile-perf/compact-thread-snapshotsfrom
t3code/mobile-perf/pause-hidden-thread-timers
Draft

juliusmarminge wants to merge 1 commit into
t3code/mobile-perf/compact-thread-snapshotsfrom
t3code/mobile-perf/pause-hidden-thread-timers

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Problem

Mobile keeps thread routes mounted after you navigate away. The working-duration label (WorkingTimer) and the live subagent status (ProviderSubagentBar) each ran an ungated 1 s setInterval. It kept firing while the screen was unfocused, while the app was backgrounded or inactive, and re-rendered the hidden screen 60 times a minute.

Fix

A new hook, useVisibleSecondClock(enabled), ticks once a second only while enabled && focused && AppState === "active". When ticking resumes it re-reads Date.now() in a layout effect, so the label shows the true elapsed time on the first frame after you return. Both labels use the hook. Nothing else changes: the visible tick rate and interval phase stay the same.

The hook also re-reads AppState.currentState after its listener is attached. This closes a small race where a change between the first render and the passive subscription would otherwise be missed. A focused regression test covers it, and that test fails without the re-read.

jsdom is now declared as an apps/mobile devDependency, matching apps/web's ^30.0.1. The new test file uses it. Before this, it resolved only through the workspace's Vite+ peer. The lockfile change is three lines on the mobile importer and pulls in no new packages.

Before / after

Measured with an instrumented Vitest test that uses fake timers in jsdom. Navigation focus and AppState are mocked, and each scenario runs for 60 simulated seconds. "Before" is the parent commit's timer code, copied verbatim.

Timer Scenario Before After
WorkingTimer, ProviderSubagentBar (live) visible (focused, active) 60 commits/min 60 commits/min
both unfocused retained route 60 commits/min 0
both focused, app background 60 commits/min 0
both focused, app inactive 60 commits/min 0
WorkingTimer 600 s background → active 600 commits while hidden 0, label shows +600 s on first active render

Evidence (sanitized):

Screenshots don't apply: the visible label looks the same before and after. The change is in how often it ticks while hidden.

Limits

  • These numbers count fake-clock JS interval callbacks and React commits. They are not OS wakeups, CPU time, or battery measurements.
  • No device or simulator proof yet, which is why this PR is a draft. Still needed: a profile on a real iOS/Android device (for example Instruments Energy Log or Android Battery Historian/Perfetto) showing JS-thread wakeups while a working thread sits backgrounded or on an unfocused retained route, before vs after.
  • This covers only these two labels. It is not a full mobile battery audit.

Verification

  • vp test run apps/mobile/src/features/threads/use-visible-second-clock.test.tsx: 9/9 pass, including the new AppState race test, which fails without the fix.
  • Measurement harness: 18/18 scenarios pass.
  • apps/mobile typecheck passes. Targeted lint shows 0 errors (the warnings are already on base, in untouched code). Format passes.

Stack: #15096 → #15248 → #15385 → this PR.

Implemented with Claude Opus 5.5 (1M context) in Claude Code via T3 Code.

🤖 Generated with Claude Code

@juliusmarminge
juliusmarminge added this pull request to stack #15249 October 3, 2026 23:58
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 3, 2026
@juliusmarminge juliusmarminge added macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews and removed size:M 30-99 changed lines (additions + deletions). labels Oct 3, 2026 — with Cursor
@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 5.0 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 20.9 KiB — 29.3 KiB ✅
Codex Live turn messages — 2 — 8 ✅
Claude Total thread wire — 5.0 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 21.2 KiB — 29.3 KiB ✅
Claude Live turn messages — 2 — 8 ✅

Baseline: unavailable · PR result: 4b291fc · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Retained thread routes kept their 1s working/subagent timers running while
unfocused or backgrounded. useVisibleSecondClock ticks only while enabled,
focused and active, and re-reads the clock before paint on resume.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@juliusmarminge
juliusmarminge force-pushed the t3code/mobile-perf/pause-hidden-thread-timers branch from 56fac3d to 4b291fc Compare October 4, 2026 23:25
@github-actions github-actions Bot added the size:M 30-99 changed lines (additions + deletions). label Oct 4, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant