Skip to content

windows_x64_asan: onnxruntime_test_all single-process run OOMs at the 8 GB SizeClassAllocator ceiling #29139

Description

Problem

The windows_x64_asan / build_x64 pipeline runs the entire onnxruntime_test_all gtest suite in a single process. In cmake/onnxruntime_unittests.cmake each unit-test binary is registered as one add_test entry (no gtest_discover_tests), so ctest --parallel <N> parallelizes across distinct binaries but never within onnxruntime_test_all. Because AddressSanitizer retains freed allocations (quarantine + per-size-class regions), one long-lived process accumulates a monotonically rising high-water mark across the whole suite.

That high-water periodically hits AddressSanitizer's per-size-class region ceiling:

AddressSanitizer: Out of memory. The process has exhausted 8192MB for size class 8192

This 8192 MB is architectural, not a tunable: it is the fixed per-size-class region of compiler-rt's SizeClassAllocator used by the MSVC ASan runtime. Two consequences worth stating up front:

  • It is not raisable via ASAN_OPTIONS — there is no runtime knob to enlarge a size-class region.
  • It is independent of physical RAM — it is an address-space/region cap, so a larger runner does not raise it. The failure means too many ~8 KB allocations are simultaneously live or quarantined in that one class, not that the machine ran out of memory.

This is recurring, and the suite is sitting right at the edge:

We hit it again while validating a small, behavior-correct change (#29084): the job flipped green→red on this exact size-class exhaustion in an unrelated SessionState test — i.e. the suite tipped over from cumulative footprint, not from anything specific to the change. The recurring pattern suggests the single-process model, rather than any individual test, is the structural cause.

Proposal

Primary (durable) — shard onnxruntime_test_all under ASan into a few fresh processes.
Use gtest's built-in sharding (GTEST_TOTAL_SHARDS / GTEST_SHARD_INDEX) to register a small number of ctest entries (e.g. 4–8) for onnxruntime_test_all, gated to the ASan configuration to contain blast radius. Each shard runs in its own process, so ASan's high-water resets between shards and no single process approaches the size-class ceiling. This removes the failure mode structurally instead of chasing it per-PR. (Avoid gtest_discover_tests, which runs the instrumented binary at configure time and explodes the ctest entry count.)

Secondary (cheap stopgap) — set ASAN_OPTIONS in the ASan job. e.g. ASAN_OPTIONS=quarantine_size_mb=64:allocator_release_to_os_interval_ms=0. Lowering quarantine releases freed chunks sooner and may buy headroom. Caveat: this reduces retention but does not raise the size-class cap, so it helps only if the pressure is quarantine-held freed chunks — it is a mitigation, not a guaranteed fix, and it slightly narrows use-after-free coverage.

Explicitly not recommended — a bigger runner. As noted above, the 8192 MB is a per-size-class region cap independent of physical RAM; more memory will not raise it. Flagging this to preempt the intuitive "just use a larger box."

Current practice — per-case test trimming (#28797, #28783) keeps unblocking individual PRs, but it is a recurring tax: every heavy new test re-tips a suite that already runs at the edge.

Suggested next step

If the sharding approach sounds reasonable, we're happy to prototype the ASan-gated GTEST_TOTAL_SHARDS wiring in cmake/onnxruntime_unittests.cmake + tools/ci_build/build.py and open a PR for review. We wanted to align on direction first rather than change shared CI execution unilaterally — input from the build-CI maintainers on the preferred approach would be very welcome.

(Environment: --config Debug --enable_address_sanitizer → MSVC /fsanitize=address; runner 1ES.Pool=onnxruntime-github-vs2022-mms; no ASAN_OPTIONS currently set anywhere in CI/build config.)

/cc Dmitri Smirnov (@yuslepukhin) Xavier Dupré (@xadupre) — you reviewed the same-signature OOM fixes (#28797 / #28783).
FYI Hariharan Seshadri (@hariharans29) (context: #29072).
(Suggested assignee: Tianlei Wu (@tianleiwu) — author/merger of #28675 and #28797.)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions