Sitelet https://github.com/dotnet/dotnet/pull/9723
Skip to content

[Experiment] Combine no-emsdk builds with runtime bootstrap - #9723

Draft
mmitche wants to merge 19 commits into
dotnet:mainfrom
mmitche:mmitche/experiment-no-emsdk-bootstrap
Draft

mmitche wants to merge 19 commits into
dotnet:mainfrom
mmitche:mmitche/experiment-no-emsdk-bootstrap

Conversation

@mmitche

@mmitche mmitche commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Experiment

Measure the combined effect of omitting emsdk production and integrating runtime bootstrap:

The combined head is ce047c62617441ec3a4b2d67a1dbd41936c778e8, based on main 64e2b5e7e3fa411000bb065686815134f6d45c89. Both original PRs remain unchanged. The merge is conflict-free and preserves newer main changes in the native build projects.

Normal repository parallelism, worker budgets, job placement, and pipeline configuration are unchanged. This is not the earlier filtered-cache combination in #9695: emsdk is not scheduled at all, through either SDK or browser-runtime dependency edges. The upstream DOTNET subset optimization is separate in dotnet/emscripten#293.

Controls and measurements

The isolated no-emsdk comparison passed all nine jobs on both sides and measured:

Measurement Main 1611195 No emsdk 1611183
Windows x64 Build step 1h54m31s 1h35m04s
Windows x64 whole job 2h05m45s 1h43m48s
Windows x86 Build step 1h17m35s 1h20m38s
Ubuntu x64 Build step 1h21m04s 1h04m15s
Browser Build step 1h06m19s 31m43s

Use those source-matched controls for the combined run only after verifying its actual merge parent and worker images. Windows controls used image 2026.0917.170346; Linux host images were 2026.0831.210244. If the environment rotates, report the mismatch rather than treating old measurements as a controlled comparison.

Measure both:

  • Total effect: main versus combined.
  • Incremental bootstrap effect: no emsdk alone versus combined.

Keep Build-step and whole-job durations distinct. Include runtime/compiler component spans, browser's dependency chain, summed Windows job time, and queue delays separately. Do not add isolated percentages or compare this newer main against earlier c567e8ff13b8 cohorts.

Validation and limits

Local checks passed 41 runtime bootstrap graph/layout assertions and fourteen before/after VMR reference configurations. Only emsdk disappears from the graph; other references and build-pass metadata are preserved. The production delta is exactly the two graph-removal files plus the existing runtime-bootstrap changes.

This remains a performance experiment, not a shipping-ready emsdk-removal change. It inherits the known missing-package/version-wiring limitations from #9717: the SDK workload manifest still references runtime-versioned Emscripten packs that are not produced, and official VS insertion/2xx+ MSI reuse paths need independent Emscripten version wiring. Those fixes are deliberately excluded from this measurement.

Verify from completed CI that integrated runtime bootstrap actually executes, emsdk does not execute in Build or Run Tests, and browser toolchain acquisition succeeds. A green lite matrix does not validate full workload/MSI publishing.

Runs

Variant Run Source
Main control 1611195 64e2b5e7e3fa
No emsdk alone 1611183 merge 55885eaed9ca, head b1ee79ead89
No emsdk plus bootstrap 1611378 merge befa2354d564, head ce047c626174

The queued merge parent is exactly 64e2b5e7e3fa, matching both controls. Pipeline 278 revision 31 and PR auto-to-lite scope are verified. All three runs passed nine jobs, and worker image versions match. The completed total and incremental measurements follow.

Completed three-way comparison

All three runs passed all nine jobs on their first attempts:

Source baselines, pipeline revision 31, and worker image versions match. All compared Windows jobs used 2026.0917.170346; the compared Linux hosts used 2026.0831.210244. Workers differ, and there is one observation per variant, not a repeated/randomized benchmark.

Build-step times

Build step Main No emsdk No emsdk + bootstrap Combined vs main
Windows x64 1h54m31s 1h35m04s 1h24m48s -29m43s (-26.0%)
Windows x86 1h17m35s 1h20m38s 1h14m35s -2m59s (-3.9%)
Ubuntu x64 1h21m04s 1h04m15s 59m36s -21m28s (-26.5%)
Browser short-stack 1h06m19s 31m43s 30m07s -36m12s (-54.6%)

Adding bootstrap on top of no-emsdk saved a further 10m16s on Windows x64, 6m02s on x86, and 4m39s on Ubuntu in this cohort. The browser commands do not request bootstrap; do not attribute their additional 1m36s difference to the bootstrap change. Browser's large total gain comes from removing the former emsdk prerequisite.

Whole-job times (distinct from Build steps)

Whole job Main No emsdk No emsdk + bootstrap
Windows x64 2h05m45s 1h43m48s 1h32m54s
Windows x86 1h22m17s 1h25m59s 1h18m36s
Ubuntu x64 1h31m04s 1h12m42s 1h08m00s
Browser short-stack 1h13m52s 36m59s 35m31s

The whole Windows x64 job saved 32m50s (26.1%) versus main and 10m54s versus no-emsdk alone. Summed Windows job time fell by 36m31s (17.6%) versus main and 18m16s versus no-emsdk. Queue time and manual-only extra validation jobs are excluded.

Component evidence

Runtime repository Main No emsdk Combined
Windows x64 81m26s 61m57s 54m06s
Windows x86 46m58s 48m12s 41m14s
Ubuntu x64 63m01s 47m34s 43m14s

The incremental runtime reductions are 7m51s on x64, 6m58s on x86, and 4m20s on Ubuntu. Logs confirm creation of the integrated bootstrap layouts and publishing from the isolated bootstrap-build trees on all three platforms.

The combined x64 Roslyn/F# spans were longer than no-emsdk alone (25m39s/22m11s versus 20m27s/17m24s), but both finished before runtime. Do not infer a precise contention percentage from these durations or assume every component gets faster.

No emsdk repository execution appears in either Build or Run Tests for the combined Windows, Ubuntu, or Browser jobs. Pipeline definitions, worker budgets, and normal repository parallelism remain unchanged.

Conclusion: unlike the earlier filtered-cache combination, removing emsdk entirely and integrating bootstrap both reduced the measured Windows x64 end-to-end build duration in this source/image-matched cohort. The roughly 26% total reduction is an observed result, not a promised average.

The known workload package-version, VS staging/MSI reuse, dependency-flow, and publishing issues remain outside this experiment. Passing the lite matrix does not make this a shipping-ready emsdk-removal change, and no package/output-equivalence claim is made for this deliberate producer removal.

Note

This experiment and description were prepared with GitHub Copilot.

mmitche and others added 19 commits August 21, 2026 18:23
Transplant the runtime bootstrap redesign so VMR builds produce the live runtime layout and consume it within one MSBuild traversal, without a separate bootstrap build or broad artifact deletion.

Runtime prototype: bbf45b5c5d6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Mirror distro-specific runtime-pack contents under PortableTargetRid inside the bootstrap snapshot so offline source-build tools such as Crossgen2 can resolve linux-x64 from a centos-specific product build.

Runtime prototype: 4eac2967a15

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Keep NativeAOT bootstrap consumers out of the root restore graph, then restore and build them after the live bootstrap layout exists. Build HostModel before those consumers to avoid rebuilding a loaded dependency.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
The runtime wrapper invokes Restore as a target rather than setting a Restore property during Build, so post-layout consumers must request Restore explicitly before Build.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Restore bootstrap consumers after layout creation, then invoke their default targets so publish projects emit native tools. Defer Crossgen2 pack projects across the same boundary to keep static-graph restore from reaching the live Crossgen2 consumer early.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Run the bootstrap producer subset as a parallel lane instead of using a traversal-wide serial boundary. Defer packages that consume published bootstrap outputs into that lane while leaving independent host packaging in the main graph.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c526c1c5-1b5c-40e8-a521-3320dc3689e9
Preserve current host-tool selection and Python discovery while retaining integrated bootstrap orchestration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Create the reusable layout at the shared producer boundary, derive deferred consumers and packages from subsets, preserve legacy and library-test flows, and normalize isolated consumer properties. Add graph and snapshot regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename the package metadata, selected project items, build target, and package properties consistently, and update graph regression checks. No scheduling or property values change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the SDK and browser runtime dependency edges to measure the cost of building emsdk. Leave all other scheduling and consumer behavior unchanged; package publishing and workload-version implications remain explicit experiment limitations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Combine dotnet#9717 at b1ee79e with dotnet#8618 at 19c3cf9 on main 64e2b5e. Preserve both isolated PRs and normal repository parallelism. Keep known workload version/publishing gaps separate from this build-performance experiment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service
dotnet-policy-service Bot requested a review from a team September 24, 2026 21:26
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