Skip to content

Stop the main thread freezing for seconds after login - #329

Merged
timgent merged 1 commit into
mainfrom
claude/login-freeze-sync-69r3jb
Aug 25, 2026
Merged

Stop the main thread freezing for seconds after login#329
timgent merged 1 commit into
mainfrom
claude/login-freeze-sync-69r3jb

Conversation

@timgent

@timgent timgent commented Aug 25, 2026

Copy link
Copy Markdown
Owner

Logging in froze the app for 4-6 seconds with the nav bar already on
screen. Profiling it (new harness: scripts/perf/login-repro.mjs) shows the
wait tracks the CPU throttle, not pod latency: it is one long task, not a
sync waiting on the network.

The task is @inrupt/solid-client's fromRdfJsDataset. It accumulates the
parsed quads immutably, spreading the whole graph object to add each
subject, so it costs O(quads x subjects). The question set is the one
document that grows on both axes at once — every person, question, option
and item lives in it — and at 5,182 quads over 1,085 subjects that single
conversion took 1,044ms unthrottled and 4.6s on a mid-range phone. The
Turtle parse it follows takes 25ms.

So build the same structure in one linear pass instead (rdfDataset.ts,
9ms for the same document; rdfDataset.test.ts asserts it equals
fromRdfJsDataset's own output for the app's real documents), and split
the fetch from the parse in loadMultipleRdfFromPod so a container's files
still download in parallel but their parses take a yield between them
rather than draining back to back in one task.

Same pod, same throttle, before -> after: longest frozen frame 6,492ms ->
281ms, total blocking time 6,799ms -> 518ms, lists on screen 11,665ms ->
5,461ms.

Owning the parse also fixes the conditional-GET cache, which never fired
against a real pod: solid-client cannot construct its FetchError for a
304, so the error loadRdfFromPod caught carried no statusCode to match on
and the load failed instead of returning the cached result. The test
covering it passed because it mocked the error solid-client would have
thrown rather than the one it does; it now drives a real 304 Response
through the real path.

Findings and numbers: docs/login-performance.md.

Also fixes two things this ran into: the solid-dev skill's start.sh picked
up two URLs from the CSS controls JSON and so never created its pod, and
the perf harnesses' shared login helper was stale against the current
provider picker.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01EAwB4CtuLyPZvRnwAyayCP

Logging in froze the app for 4-6 seconds with the nav bar already on
screen. Profiling it (new harness: scripts/perf/login-repro.mjs) shows the
wait tracks the CPU throttle, not pod latency: it is one long task, not a
sync waiting on the network.

The task is @inrupt/solid-client's fromRdfJsDataset. It accumulates the
parsed quads immutably, spreading the whole graph object to add each
subject, so it costs O(quads x subjects). The question set is the one
document that grows on both axes at once — every person, question, option
and item lives in it — and at 5,182 quads over 1,085 subjects that single
conversion took 1,044ms unthrottled and 4.6s on a mid-range phone. The
Turtle parse it follows takes 25ms.

So build the same structure in one linear pass instead (rdfDataset.ts,
9ms for the same document; rdfDataset.test.ts asserts it equals
fromRdfJsDataset's own output for the app's real documents), and split
the fetch from the parse in loadMultipleRdfFromPod so a container's files
still download in parallel but their parses take a yield between them
rather than draining back to back in one task.

Same pod, same throttle, before -> after: longest frozen frame 6,492ms ->
281ms, total blocking time 6,799ms -> 518ms, lists on screen 11,665ms ->
5,461ms.

Owning the parse also fixes the conditional-GET cache, which never fired
against a real pod: solid-client cannot construct its FetchError for a
304, so the error loadRdfFromPod caught carried no statusCode to match on
and the load failed instead of returning the cached result. The test
covering it passed because it mocked the error solid-client would have
thrown rather than the one it does; it now drives a real 304 Response
through the real path.

Findings and numbers: docs/login-performance.md.

Also fixes two things this ran into: the solid-dev skill's start.sh picked
up two URLs from the CSS controls JSON and so never created its pod, and
the perf harnesses' shared login helper was stale against the current
provider picker.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAwB4CtuLyPZvRnwAyayCP
@vercel

vercel Bot commented Aug 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-packing-app Ready Ready Preview Aug 25, 2026 7:08am

@timgent
timgent merged commit 7507114 into main Aug 25, 2026
4 checks passed
@timgent
timgent deleted the claude/login-freeze-sync-69r3jb branch August 25, 2026 12:28
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.

2 participants