Skip to content

PAC-3: libraries stop choosing their users' allocator and GPU stack - #93

Merged
physics515 merged 2 commits into
xname/declare-validationfrom
pac3/library-hygiene
Oct 21, 2026
Merged

physics515 merged 2 commits into
xname/declare-validationfrom
pac3/library-hygiene

Conversation

@physics515

Copy link
Copy Markdown
Collaborator

Closes the wave 2 box in ROADMAP.md:

PAC-3 Library crate hygiene: no global allocator or wgpu features imposed on library users

Stacked on #92 (ROB-2), which is stacked on #91 (X-NAME) and #90 (X-ERR).

The allocator

turso 0.8.1 carries this in its own crate root:

#[cfg(all(feature = "mimalloc", not(target_family = "wasm"), not(miri)))]
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;

This workspace asked turso for mimalloc, and weftdb — a published library — inherited that
dependency. So every program that linked weftdb had its process allocator replaced with mimalloc:
an embedder that sets its own, one that wants the system allocator, one that ships to a platform
where mimalloc is the wrong call. A library cannot make that decision for the process it runs in.

  • The workspace no longer asks for it: turso = { version = "0.8", default-features = false }.
  • weft-server and weft-tui now depend on mimalloc directly and declare it in their own main.rs.
    That is the edit the plan's L-MAIN lane already schedules — docs/release/1.0-plan.md:126, "Later
    main.rs edits, one per wave: PAC-3 (W2, #[global_allocator])" — so the choice now sits in the
    file that owns the process.
  • Nothing about our binaries' measured behaviour moves: same crate, same version (mimalloc 0.1.52 with
    libmimalloc-sys 0.1.49, both already in Cargo.lock and THIRD-PARTY-LICENSES.md), same allocator,
    chosen by the binary that runs it. weft-bench never linked weftdb and never had mimalloc, so it
    does not change.

wgpu

splimes = "1" at the workspace level took splimes' default features, and gpu is one of them:
gpu → wgpu → the Vulkan, Metal and DX12 backends. Five library crates depend on splimes, so a
program that linked weft-line-protocol to parse a text line was pulling a GPU driver stack into its
build and its binary.

The workspace line is now splimes = { version = "1", default-features = false, features = ["serde"] }.
The two executables that call the GPU API — weft-server and weft-bench, through prewarm_gpu,
calibrate and gpu_pool_stats — enable gpu themselves, and weftdb's interpolation benches get it
as a dev-dependency, so every GPU path this repository runs is still compiled and still exercised.

tracing-subscriber

Moved from weftdb's [dependencies] to [dev-dependencies]. Nothing in the library installs a
subscriber outside #[cfg(test)], so every program linking weftdb was building registry, fmt and
env-filter code it never called.

Proof

Distinct packages in each crate's non-dev dependency graph (cargo tree -p X -e normal | sort -u | wc -l),
measured before at df21a2e in a throwaway worktree and after in this branch:

crate before after
weft-line-protocol 77 25
weft-reduce 77 25
weftdb 266 227
weft-orchestration 267 231

cargo tree -p weftdb -i wgpu -e normal and cargo tree -p weftdb -i mimalloc -e normal both return
nothing on this branch; weft-server's graph still resolves both, because it asks for them.

Deliberately unchanged

  • splimes' serde stays on. weftdb::BatchedMeasurement (weftdb/src/types/batches/batch.rs:52)
    derives Serialize/Deserialize over a splimes::Resolution field. Turning it off would be a
    compile break for the crate that ships it, not hygiene.
  • turso's other default, fts, stays off, as it already was. It is turso's full-text search, and
    switching it on grows every build with tantivy, tantivy-columnar, zstd-sys and the rest of
    that tree — an early version of this line enabled it and the lock diff grew by 435 lines, which is
    how that was caught. Nothing in this workspace uses FTS.
  • No library src/ calls a splimes GPU API. The GPU callers are weft-server/src/gpu.rs,
    weft-bench/src/engine.rs and weft-bench/src/gpu_memory.rs, plus weftdb/benches/interpolate_range.rs.

What an embedder has to do

Two things a user of the published libraries may notice, both written up in CHANGELOG.md with a ⚠️:

  • Code that reached the GPU through weftdb — a splimes::Backend::Gpu while depending on weftdb
    alone — has to name splimes itself now.
  • Code that was relying on mimalloc arriving with weftdb declares it in its own binary.

One comparison to be aware of

cargo bench -p weftdb is criterion, which is not test code, so it used to inherit mimalloc through
turso and now runs on the system allocator: a weftdb bench figure taken before this release is not
directly comparable with one taken after. The Weft-Bench series, including the nightly regression track
EVI-5 will add, is unaffected.

Verification

  • cargo +stable check --workspace --all-targets --locked
  • cargo +stable clippy --workspace --all-targets --all-features --locked -- -D clippy::correctness -D clippy::suspicious -D clippy::perf
  • RUSTDOCFLAGS="-D warnings" cargo +stable doc --workspace --no-deps --locked — two crate-level doc
    lines in weftdb/src/lib.rs named splimes' GPU-only calibrate and had to be reworded, since
    rustdoc resolves a :: code span and would now fail to link it.
  • lib tests: weftdb (389), weft-server (291), weft-orchestration, weft-reduce,
    weft-line-protocol, weft-arrow
  • cargo +nightly fmt --all -- --check
  • MSRV (1.95), the feature matrix and the license bundle are CI's to confirm: no dependency version
    changes, mimalloc was already in Cargo.lock and THIRD-PARTY-LICENSES.md.

Follow-up, deliberately not in this PR

tokio with features = ["full"] sits in [workspace.dependencies] and reaches the published
libraries the same way mimalloc did — every library user gets the whole runtime, drivers, macros and
sync, whether or not they use it. Same class of leak, but the fix changes which tokio features are on
for four crates and their tests, so it deserves its own slice and its own CI run.

…PU stack

PAC-3. turso's `mimalloc` feature installs a `#[global_allocator]` in turso's own crate root, so the
workspace's turso line made `weftdb` — a published library — decide the process allocator of every
program that links it, including one with an allocator of its own or none at all. splimes' default
`gpu` feature did the same one layer over: `gpu` -> `wgpu` -> the Vulkan, Metal and DX12 backends, in
the dependency graph of five library crates.

Our own binaries lose nothing. `weft-server` and `weft-tui` now name mimalloc 0.1.52 in their own
roots, which is the edit the 1.0 plan's L-MAIN lane already schedules (docs/release/1.0-plan.md:126,
"Later main.rs edits, one per wave: PAC-3 (W2, `#[global_allocator]`). `weft-server` and `weft-bench`
ask splimes for `gpu` directly, and `weftdb`'s interpolation benches get it as a dev-dependency, so
every GPU path this repository compiles and exercises is still compiled and exercised. splimes'
`serde` stays on, because `weftdb::BatchedMeasurement` serialises a `splimes::Resolution`; turso's
other default, `fts`, stays off as it already was, since it is full-text search and pulling it in
grows the graph with tantivy, tantivy-columnar and zstd-sys. `weftdb`'s tracing-subscriber moves to dev-dependencies —
only test code installs a subscriber.

The non-dev dependency graphs, counted as distinct packages before and after: weft-line-protocol and
weft-reduce 77 -> 25, weftdb 266 -> 227, weft-orchestration 267 -> 231. Two crate-doc lines in
weftdb/src/lib.rs named splimes' GPU-only `calibrate` and are reworded, since the doc job denies
broken intra-doc links.
…cator and GPU stack

PR #93. Two decisions were being made for every program that links these
crates: turso's mimalloc feature installs a #[global_allocator] in turso's own
crate root, so asking for it on the published library weftdb chose the
allocator of every embedder's process; and splimes' default features pull wgpu,
which sat in the normal graph of four libraries that never call a GPU API.

The allocator now belongs to the executables, which is where the plan puts this
slice (docs/release/1.0-plan.md:126). GPU stays opt-in at the dependency level.
Distinct packages in the normal graph: weft-line-protocol and weft-reduce
77 -> 25, weft-orchestration 267 -> 231, weftdb 266 -> 227.

Recorded in the note: the two keeps (splimes serde for BatchedMeasurement,
turso fts left off as it already was), and that cargo bench -p weftdb is no
longer allocator-comparable across this commit.
Base automatically changed from rob2/engine-panic-failstop to xname/declare-validation October 21, 2026 15:30
@physics515
physics515 merged commit 7296a40 into xname/declare-validation Oct 21, 2026
21 checks passed
@physics515
physics515 deleted the pac3/library-hygiene branch October 21, 2026 15: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.

1 participant