Skip to content

CI: skip framework-dependent bootstrapper in self-contained /perf Rust harness (fix #674 0xC0000135)#690

Merged
azchohfi merged 1 commit into
mainfrom
azchohfi-fix-perf-rust-bootstrap
Jun 26, 2026
Merged

CI: skip framework-dependent bootstrapper in self-contained /perf Rust harness (fix #674 0xC0000135)#690
azchohfi merged 1 commit into
mainfrom
azchohfi-fix-perf-rust-bootstrap

Conversation

@azchohfi

Copy link
Copy Markdown
Collaborator

Summary

The on-demand /perf workflow's cross-framework Rust column still read n/a, with test_reactor_perf.exe exiting 0xC0000135 (DLL-not-found) at launch — even after the self-contained build (#662) and WebView2 Core staging (#689) fixes. This PR fixes the remaining root cause so the Rust column produces live numbers.

This is CI/build-script + docs only — no framework runtime code is touched.

Root cause (reproduced locally, hermetically)

I reproduced the runner failure on a local box with PATH scrubbed to System32 only (so a machine-wide Windows App SDK runtime cannot mask missing app-local DLLs), mirroring the GitHub windows-latest runner which has no machine-wide WinAppSDK runtime:

  • The windows-rs reactor_perf harness main() unconditionally calls bootstrap() (MddBootstrapInitialize2) to locate a machine-wide Windows App SDK runtime.
  • windows_reactor_setup::as_self_contained() (which the workflow already patches build.rs to call) never stages the framework-dependent bootstrapper — only as_framework_dependent calls copy_bootstrap_to.
  • So the self-contained exe carries an unsatisfiable load-time PE import on Microsoft.WindowsAppRuntime.Bootstrap.dll (confirmed with dumpbin /imports). On the runtime-less runner the loader fails before main runs0xC0000135, instant exit, 0-byte stdout/stderr → the 100s watchdog reports n/a.
  • Second layer: even if that DLL is staged, MddBootstrapInitialize2(..., OnNoMatch_ShowUI | ...) looks for a machine-wide framework package and fail-fasts headless (0xC0000602) when none is present. So staging the DLL is necessary-but-insufficient — the bootstrap call itself must be neutralized. (This is why CI: stage WebView2 Core DLL so the /perf Rust column runs (fix #674) #689's staging alone didn't fix it.)

MddBootstrapInitialize2's own documentation: "Self-contained apps do not need to call this." The harness's embedded reg-free app.manifest activates the runtime app-local.

The fix

In the workflow's "Prepare Rust harness" step, alongside the existing build.rsas_self_contained() patch, comment out the single bootstrap()?; call in the cloned harness main.rs:

$patched = [regex]::Replace($src, '(?m)^(?<indent>[ \t]*)bootstrap\(\)\?;', '${indent}// bootstrap()?; // ...')

Why it's safe:

  • Benchmark-neutral. main()'s bootstrap() is deployment-mode setup (runtime discovery), not the measured StocksGrid workload. Removing it is directly analogous to the existing build.rs as_self_contained() patch and does not affect the four target metrics.
  • Best-effort. If upstream ever moves the call so the regex stops matching, the step logs a warning and the column reads n/a — it never fails the job, and the PR-vs-main C# comparison is entirely unaffected (the Rust leg is continue-on-error).
  • Stage-RustRuntime is unchanged — the runtime MSIX payload + Microsoft.Web.WebView2.Core.dll (manifest-declared SxS) are still staged app-local; this fix removes the need for the bootstrapper, it doesn't change staging.

Local verification

Applying the exact workflow patches (build.rs + main.rs regex) to the pinned windows-rs checkout, rebuilding, and running hermetically:

  • dumpbin confirms the Microsoft.WindowsAppRuntime.Bootstrap.dll import is gone from the rebuilt exe.
  • ✅ Hermetic, PATH-scrubbed run → exit 0 with full metrics (Renders/sec, Reconcile, Diff, Memory).
  • ✅ Loaded-module snapshot: all WinAppSDK DLLs resolve from the app-local staging dir (zero from C:\Program Files\WindowsApps) — proving the fix is genuinely runtime-independent, not masked by my box's installed runtime.
  • ✅ Regex unit-validated: matches exactly one call site, preserves indentation, idempotent, leaves no bare bootstrap()?;.

I also confirmed the before state: the unpatched exit is 0xC0000135 (matching the runner), and the DLL-staged-but-call-present exit is 0xC0000602 (the fail-fast), exactly as the root-cause analysis predicts.

Validation run locally

  • tests/stress_perf/ci/PerfLib.Tests.ps161/61
  • tests/stress_perf/ci/RunPerfBenchmark.Tests.ps121/21
  • Workflow YAML parses ✅; the step's embedded PowerShell AST parses with 0 errors

Note: the local dotnet build Reactor.slnx -c Release surfaces a pre-existing, unrelated ARM64-dev-box XAML markup-compiler failure (issue #678, fixed by the separate open PR #684XamlCompiler.exe MSB3073 on long paths). It does not occur on x64 windows-latest CI runners and is independent of this YAML+docs change (neither file is an MSBuild compiler input).

Final acceptance test

This can only be fully validated by a live /perf re-run on a pre-gate PR (e.g. comment /perf on #656). A maintainer should run that as the final acceptance step; the local hermetic repro + module-path proof above are the strongest evidence achievable off-runner.

Refs

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

…t harness (fix #674 0xC0000135)

The on-demand /perf workflow's cross-framework Rust column still read n/a with
test_reactor_perf.exe exiting 0xC0000135 (DLL-not-found), even after the
self-contained build (#662) and WebView2 staging (#689) fixes.

Root cause (reproduced locally, hermetically, with PATH scrubbed to System32):
the windows-rs reactor_perf harness main() unconditionally calls bootstrap()
(MddBootstrapInitialize2) to locate a *machine-wide* Windows App SDK runtime.
windows_reactor_setup::as_self_contained() never stages the framework-dependent
bootstrapper, so the exe carries an unsatisfiable load-time import on
Microsoft.WindowsAppRuntime.Bootstrap.dll. On the runtime-less runner the loader
fails before main runs -> 0xC0000135, 0-byte output, watchdog reports n/a. (Even
with the bootstrap DLL staged, MddBootstrapInitialize2 fail-fasts headless with no
machine-wide package -> 0xC0000602, so staging the DLL is necessary-but-insufficient.)

Fix: in the "Prepare Rust harness" step, alongside the existing build.rs ->
as_self_contained() patch, comment out the single bootstrap()?; call in the
harness main(). Self-contained apps don't need it: the embedded reg-free
app.manifest activates the runtime app-local. Dropping the call removes the import;
a loaded-module snapshot confirms all WinAppSDK DLLs then resolve from the
app-local staging dir (zero from C:\Program Files\WindowsApps).

Benchmark-neutral (it changes runtime discovery, not the measured StockGrid
workload, analogous to the build.rs patch) and best-effort: the patch warns
(does not fail) if upstream moves the call, leaving the Rust column at n/a without
affecting the PR-vs-main C# comparison.

Verified end-to-end locally: applying the exact workflow patches to the pinned
windows-rs checkout, rebuilding, and running hermetically yields exit 0 with full
metrics; dumpbin confirms the Bootstrap.dll import is gone. Final acceptance is a
live /perf re-run on a PR (e.g. #656).

Refs #674, #662, #677, #689.

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 fixes the /perf workflow’s Rust cross-framework column by ensuring the pinned windows-rs perf harness can launch on runners without a machine-wide Windows App SDK runtime, by neutralizing the harness’s framework-dependent bootstrapper call while keeping the self-contained staging approach.

Changes:

  • Patch the pinned windows-rs reactor_perf harness to comment out bootstrap()?; in main.rs, preventing load-time dependency on Microsoft.WindowsAppRuntime.Bootstrap.dll on runtime-less CI runners.
  • Update the stress perf CI README to document why the bootstrap call must be removed for the self-contained Rust harness and how the failure surfaces (0xC0000135 / 0xC0000602).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
.github/workflows/perf-compare.yml Adds a best-effort PowerShell patch that comments out the Rust harness bootstrap() call to avoid framework-dependent bootstrapper imports on CI.
tests/stress_perf/ci/README.md Documents the Rust self-contained harness patching rationale and troubleshooting guidance for 0xC0000135 “n/a” failures.

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

@azchohfi azchohfi merged commit 1402d1c into main Jun 26, 2026
21 checks passed
@azchohfi azchohfi deleted the azchohfi-fix-perf-rust-bootstrap branch June 26, 2026 03:31
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