Skip to content

Bound-parallelize indexer module pre-warm#5046

Open
habdelra wants to merge 3 commits into
cs-11306-module-definition-pre-warm-is-a-silent-no-op-in-the-indexerfrom
cs-11306-prewarm-concurrency
Open

Bound-parallelize indexer module pre-warm#5046
habdelra wants to merge 3 commits into
cs-11306-module-definition-pre-warm-is-a-silent-no-op-in-the-indexerfrom
cs-11306-prewarm-concurrency

Conversation

@habdelra
Copy link
Copy Markdown
Contributor

@habdelra habdelra commented May 30, 2026

Background and Goal

Stacked on #5042. Now that the indexer's module pre-warm actually populates the definition cache, this makes the populate loop's fan-out tunable via INDEXER_PREWARM_CONCURRENCY so it can be benchmarked against a given prerender-pool envelope.

Where to start

  • packages/runtime-common/index-runner.tspreWarmModulesTable drains the candidate set with a bounded worker pool; prewarmConcurrency() resolves the width from INDEXER_PREWARM_CONCURRENCY.

Key decisions

  • Serial by default (INDEXER_PREWARM_CONCURRENCY=1). Measured against a cold/shared prerender pool, concurrent pre-warm is a regression, not a win: visit renders run with flags=[reused], so serial pre-warm reuses a single warm tab, whereas firing N concurrent module prerenders forces the pool to materialize one Chrome tab per in-flight request — and that tab-startup cost outweighs the parallelism for the fast definition-extraction renders pre-warm fires. (In CI this surfaced as a ~16–21% per-realm indexing slowdown.) So the default preserves the proven serial behavior and parallelism is opt-in.
  • Opt-in ceiling = the per-affinity tab budget (PRERENDER_AFFINITY_TAB_MAX): a realm's pre-warm targets one prerender affinity, so beyond that the requests just queue at the server's per-affinity admission. Raise the env var only where the pool is pre-sized for the extra concurrent module renders.
  • Safety is free. DefinitionLookup already owns the in-flight dedup and the cross-process advisory-lock coalescer, so different modules populate independently while same-URL callers share one prerender; per-module try/catch failure accounting is preserved (a failed warm never fails the batch). Module renders don't recurse into same-affinity sub-prerenders, so raising the width can't reintroduce the file→module deadlock.

The pre-warm loop populated the definition cache one module at a time. Fan
it out with a bounded worker pool so independent module prerenders run
concurrently (DefinitionLookup already dedups same-URL callers in-flight
and across processes). Concurrency is tunable via INDEXER_PREWARM_CONCURRENCY
and defaults to 5, aligned with the prerender server's per-affinity tab
budget (PRERENDER_AFFINITY_TAB_MAX): a single realm's pre-warm targets one
prerender affinity, so beyond that the requests just queue at the server's
per-affinity admission instead of adding real parallelism.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: db70413f6b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/runtime-common/index-runner.ts
The serial-vs-parallel rollout narrative no longer describes the code now
that the populate loop is bound-parallelized.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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 parallelizes the indexer’s module pre-warm step with a bounded worker pool so aggregate-card-heavy realms can better use prerender capacity before the visit phase.

Changes:

  • Adds INDEXER_PREWARM_CONCURRENCY parsing with a default concurrency of 5.
  • Replaces the serial pre-warm loop with bounded concurrent workers.
  • Extends pre-warm performance logging to include candidate count, failures, and concurrency.

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

Comment thread packages/runtime-common/index-runner.ts Outdated
@habdelra habdelra requested a review from a team May 30, 2026 00:13
Firing concurrent module prerenders forces a cold/shared prerender pool to
materialize one Chrome tab per in-flight request, whereas serial pre-warm
reuses a single warm tab — and the per-tab startup cost outweighs the
parallelism for the fast definition-extraction renders pre-warm fires.
Default INDEXER_PREWARM_CONCURRENCY to 1 (serial); raise it only where the
prerender pool is pre-sized for the extra concurrent module renders.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 30, 2026

Host Test Results

    1 files  ±0      1 suites  ±0   1h 48m 35s ⏱️ + 2m 44s
2 842 tests ±0  2 827 ✅ ±0  15 💤 ±0  0 ❌ ±0 
2 861 runs  ±0  2 846 ✅ ±0  15 💤 ±0  0 ❌ ±0 

Results for commit a5f27e3. ± Comparison against earlier commit 20041fb.

Realm Server Test Results

    1 files  ±  0      1 suites  ±0   13m 12s ⏱️ + 3m 1s
1 517 tests +554  1 516 ✅ +555  1 💤 +1  0 ❌  - 2 
1 608 runs  +594  1 607 ✅ +595  1 💤 +1  0 ❌  - 2 

Results for commit a5f27e3. ± Comparison against earlier commit 20041fb.

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