Skip to content

CS-11123 Phase 2: Bound-parallelize pre-warm walk#4800

Closed
habdelra wants to merge 1 commit into
cs-11123-prewarm-phase1from
cs-11123-prewarm-phase2
Closed

CS-11123 Phase 2: Bound-parallelize pre-warm walk#4800
habdelra wants to merge 1 commit into
cs-11123-prewarm-phase1from
cs-11123-prewarm-phase2

Conversation

@habdelra
Copy link
Copy Markdown
Contributor

@habdelra habdelra commented May 13, 2026

Summary

  • Replace Phase 1's serial pre-warm loop with a bounded-parallel walk: N workers (cap = 4, PRE_WARM_MAX_CONCURRENCY) pull from a shared queue of module URLs and call getModuleCacheEntry per slot.
  • Parallelize the upfront adoptsFrom.module source reads (HTTP via reader.readFile in the worker process) for novel .json invalidations — bounded by the same cap.
  • Concurrent same-URL callers continue to coalesce through CachingDefinitionLookup's #inFlight map, so parallel pre-warm never duplicates a prerender.

Bound rationale. The cap of 4 matches the planned INDEX_RUNNER_MAX_CONCURRENCY from the sibling parallel-visit-loop work. The cap is on admission here only — the prerender server's affinity-scoped tab queue still owns the real back-pressure against the pool; bounding here just keeps the websocket fan-out from spiking on large invalidation sets.

Built on top of Phase 1 (#4799). Base this PR's merge against main after Phase 1 lands; until then it targets the Phase 1 branch.

Test plan

  • Bench /prudent-octopus reindex on top of this PR — total wall-clock drops vs Phase 1, no new instanceErrors.
  • Bench /ambitious/prianha reindex on top of this PR — still completes, total wall-clock drops vs Phase 1.
  • Confirm pre-warm walk wall-clock drops measurably vs Phase 1 (proportional to module count and concurrency, modulo prerender-pool contention).
  • If Phase 2 does not deliver a measurable win over Phase 1 — for instance because the prerender pool is already saturated by the upcoming parallel file-visit phase — close this PR and ship Phase 1 + Phase 3 only.
  • Existing realm-server indexing integration tests still pass.

🤖 Generated with Claude Code


Bench results (vite-dev rig, 2026-05-13)

Same-rig as the prior main baseline (commit 0119bac76d) and the Phase 1 numbers in #4799. Protocol: mise run kill-allTRUNCATE job_reservations, jobs, job_progressmise run dev-all → boot drain → readiness-check mount → mount drain → time curl /_grafana-reindex.

Realm SHA Wall (s) Status fed-search hits filesIndexed instancesIndexed instanceErrors
user/prudent-octopus main 0119bac76d 617 resolved 120 118 91 0
user/prudent-octopus Phase 1 c85633d237 467 resolved 176 118 91 0
user/prudent-octopus Phase 2 d386c145a1 512 resolved 174 118 91 0
user/ambitious-piranha main 0119bac76d 652 rejected (500) 614
user/ambitious-piranha Phase 1 c85633d237 195 rejected (500) 18
user/ambitious-piranha Phase 2 d386c145a1 189 rejected (500) 18

Phase 2 does not deliver a measurable win

Octopus on Phase 2 is 45 s slower than Phase 1 (512 s vs 467 s, +9.6 %), not faster. Piranha is unchanged — still rejects at the 150 s prerender-server abort during the first cohort render.

The likeliest read: the prerender pool's affinity-scoped tab queue is already serializing module renders inside the per-realm affinity, so bounded-parallel admission at the indexer doesn't expand the effective concurrency — it just adds a small overhead (extra promise scheduling, more concurrent #inFlight map churn) that surfaces as the +45 s drift.

Phase 2 pass-bar status

  • ❌ Octopus wall-clock does not drop measurably vs Phase 1; it rises by 45 s.
  • ❌ Piranha unchanged — still rejects.
  • Phase 2 fails the ticket's pass-bar: "If Phase 2 doesn't deliver a measurable win over Phase 1 … note it and stop. Don't ship parallelism that doesn't show up in the numbers."

Recommendation: close this PR. Ship Phase 1 (serial pre-warm, with the adoptsFrom fix that resolves the octopus instanceError) and Phase 3 (cacheOnlyDefinitions unwind, conditional on piranha being addressable elsewhere) without the parallel walk.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements CS-11123 Phase 2 by converting the module pre-warm step in IndexRunner from a serial loop into a bounded-parallel walk, aiming to reduce pre-warm wall-clock time on large invalidation sets while relying on existing in-flight deduplication in CachingDefinitionLookup.

Changes:

  • Introduces PRE_WARM_MAX_CONCURRENCY = 4 to cap concurrent getModuleCacheEntry() pre-warm work.
  • Replaces the serial pre-warm loop with a worker-queue pattern that processes module URLs in bounded parallel.
  • Parallelizes resolving novel .json invalidations’ adoptsFrom.module reads via Promise.all(...).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/runtime-common/index-runner.ts Outdated
Comment thread packages/runtime-common/index-runner.ts Outdated
@habdelra habdelra force-pushed the cs-11123-prewarm-phase2 branch from 5abb6e3 to f17b9a1 Compare May 13, 2026 00:26
@habdelra habdelra force-pushed the cs-11123-prewarm-phase1 branch from b144320 to 004c9b8 Compare May 13, 2026 00:26
@habdelra habdelra force-pushed the cs-11123-prewarm-phase2 branch from f17b9a1 to e6a0a7f Compare May 13, 2026 00:27
@habdelra habdelra force-pushed the cs-11123-prewarm-phase1 branch from 004c9b8 to bdd34dc Compare May 13, 2026 00:27
@habdelra habdelra force-pushed the cs-11123-prewarm-phase2 branch from e6a0a7f to 209a065 Compare May 13, 2026 00:42
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 13, 2026

Host Test Results

    1 files  ±0      1 suites  ±0   2h 0m 18s ⏱️ + 12m 31s
2 658 tests ±0  2 643 ✅ ±0  15 💤 ±0  0 ❌ ±0 
2 677 runs  ±0  2 662 ✅ ±0  15 💤 ±0  0 ❌ ±0 

Results for commit d386c14. ± Comparison against earlier commit 209a065.

Realm Server Test Results

    1 files  ±0      1 suites  ±0   12m 26s ⏱️ +48s
1 345 tests ±0  1 345 ✅ ±0  0 💤 ±0  0 ❌ ±0 
1 424 runs  ±0  1 424 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit d386c14. ± Comparison against earlier commit 209a065.

@habdelra habdelra marked this pull request as ready for review May 13, 2026 02:45
Replace Phase 1's serial pre-warm loop with a bounded parallel walk:
N workers (default PRE_WARM_MAX_CONCURRENCY = 4) pull from a shared
queue of module URLs and call `getModuleCacheEntry` per slot.
Concurrent same-URL callers continue to coalesce through
`CachingDefinitionLookup`'s `#inFlight` map, so parallel pre-warm
never duplicates a prerender.

Also parallelize the upfront `adoptsFrom.module` disk reads for the
novel `.json` invalidations — a wide invalidation set no longer pays
N sequential file reads to resolve the pre-warm URL set.

The cap of 4 matches the planned `INDEX_RUNNER_MAX_CONCURRENCY` from
the sibling parallel-visit-loop work. The cap is on _admission_ here
only — the prerender server's affinity-scoped tab queue still owns
the real back-pressure against the pool; bounding here just keeps the
websocket fan-out from spiking on large invalidation sets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@habdelra habdelra force-pushed the cs-11123-prewarm-phase2 branch from 209a065 to d386c14 Compare May 13, 2026 02:57
@habdelra habdelra force-pushed the cs-11123-prewarm-phase1 branch from bdd34dc to c85633d Compare May 13, 2026 02:57
@habdelra habdelra marked this pull request as draft May 13, 2026 07:08
@habdelra
Copy link
Copy Markdown
Contributor Author

closing this as the benchmark indicates that this worsens indexing time

@habdelra habdelra closed this May 13, 2026
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