From 7fdc59f3ae9c46d35a1bd4b6989f5271a23b5fac Mon Sep 17 00:00:00 2001 From: CodeWhale Bot Date: Sun, 6 Sep 2026 16:23:20 -0700 Subject: [PATCH] feat(build): opt-in rusty_alloc global allocator feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an off-by-default `rusty-alloc` cargo feature to codewhale-tui and codewhale-cli (#5872) that maps the `#[global_allocator]` static to rusty_alloc (the pure-Rust mimalloc v2.4.5 remake — no C compiler, no build script on that path) instead of the default mimalloc. The issue's sketch pinned `rusty_alloc` and used `rusty_alloc_api::RustyAlloc`; the GlobalAlloc impl actually lives in the `rusty_alloc-api` crate (the crate's documented surface), so that is the dependency — it pulls the rusty_alloc 1.1.6 core transitively at the same version. Default build is unchanged: the mimalloc static compiles exactly as before behind `#[cfg(not(feature = "rusty-alloc"))]`. Build with: cargo build -p codewhale-tui --features rusty-alloc Gates (worktree tmp/wt-5872-rusty-alloc, shared target dir): - cargo fmt --all: clean - cargo check -p codewhale-tui --locked: clean (2m31s) - cargo check -p codewhale-tui --locked --features rusty-alloc: clean (5m10s) - cargo check -p codewhale-cli --locked --features rusty-alloc: clean (2m04s) - cargo clippy --workspace --all-targets --all-features --locked -- -D warnings -A clippy::uninlined_format_args -A clippy::too_many_arguments -A clippy::unnecessary_map_or: clean (5m20s) - cargo deny check: advisories ok, bans ok, licenses ok, sources ok (both new crates are MIT; no deny.toml entry needed) - cargo test -p codewhale-tui --lib --locked: 11868 passed, 1 failed, 13 ignored (357s). The failure, remote_control::tests::separate_predispatch_crashes_on_one_run_get_distinct_recovery_turn_ids, passes in isolation on rerun (1 passed, 0 failed) and is unrelated to allocator wiring — the lib test target does not compile the changed src/main.rs. Reporting it as the one non-green result of the run. CHANGELOG [Unreleased] entry + sync-changelog.sh + regenerated web/lib/changelog.generated.ts (derive-changelog.mjs idempotent). Signed-off-by: CodeWhale Bot --- CHANGELOG.md | 6 ++++++ Cargo.lock | 21 +++++++++++++++++++++ Cargo.toml | 6 ++++++ crates/cli/Cargo.toml | 8 ++++++++ crates/cli/src/main.rs | 8 ++++++++ crates/tui/CHANGELOG.md | 6 ++++++ crates/tui/Cargo.toml | 6 ++++++ crates/tui/src/main.rs | 8 ++++++++ docs/BUILD_PERFORMANCE.md | 4 +++- web/lib/changelog.generated.ts | 6 +++--- 10 files changed, 75 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cd3b2cb3e..615afa1359 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- The `rusty-alloc` cargo feature on `codewhale-tui` and `codewhale-cli` + opts the binaries into the `rusty_alloc` global allocator (the mimalloc + v2.4.5 architecture remade in pure Rust — no C compiler or build script + on that path) instead of the default mimalloc. It is off by default and + the default build is unchanged; build with + `cargo build -p codewhale-tui --features rusty-alloc` (#5872). - The `/theme` picker now discovers valid user-authored `custom:` overlays, previews their colors, highlights the active overlay, and preserves it when the picker is opened and committed without navigation (#5901). diff --git a/Cargo.lock b/Cargo.lock index 482d507939..437f7eec84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -832,6 +832,7 @@ dependencies = [ "mimalloc", "reqwest 0.13.4", "rustls", + "rusty_alloc-api", "semver", "serde", "serde_json", @@ -1106,6 +1107,7 @@ dependencies = [ "rusqlite", "rust-i18n", "rustls", + "rusty_alloc-api", "schemars", "semver", "serde", @@ -4696,6 +4698,25 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" +[[package]] +name = "rusty_alloc" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c93620fee9935a120a50df2086fe48fa072f7d391f129a5e04bf20ea9b83097d" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "rusty_alloc-api" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ce52d7f72842a590e4588013d70ea02d27edbf6b6af9bc193f6e1ac173845a" +dependencies = [ + "rusty_alloc", +] + [[package]] name = "ryu" version = "1.0.23" diff --git a/Cargo.toml b/Cargo.toml index 843079a699..24e39e1e43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,6 +76,12 @@ tracing-appender = "0.2" tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } uuid = { version = "1.11", features = ["v4"] } mimalloc = { version = "0.1", default-features = false } +# Off-by-default alternative to mimalloc behind the `rusty-alloc` feature in +# codewhale-tui / codewhale-cli (#5872): the pure-Rust mimalloc v2.4.5 +# remake — no C compiler, no build script on that path. `rusty_alloc-api` is +# the crate's documented surface; it pulls the `rusty_alloc` core transitively +# at the same version. +rusty_alloc-api = "1.1.6" # The everyday `--release` gate (AGENTS.md pre-push build): optimized but # fast to produce. Shipping artifacts use `--profile dist` below — fat LTO on diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index a83544e7a3..ee96af6153 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -10,6 +10,13 @@ description = "Agentic terminal facade for open-source and open-weight coding mo [lints] workspace = true +[features] +# Opt-in global-allocator swap (#5872): build on rusty_alloc (the pure-Rust +# mimalloc v2.4.5 remake — no C compiler, no build script) instead of the +# default mimalloc. Off by default; the default build is unchanged. +# Build with: cargo build -p codewhale-cli --features rusty-alloc +rusty-alloc = ["dep:rusty_alloc-api"] + [[bin]] name = "codewhale" path = "src/main.rs" @@ -42,6 +49,7 @@ rustls.workspace = true semver.workspace = true tokio.workspace = true mimalloc.workspace = true +rusty_alloc-api = { workspace = true, optional = true } sha2.workspace = true tempfile.workspace = true tracing.workspace = true diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 781c1fe4b0..fd8081fb46 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,6 +1,14 @@ +// Default allocator: mimalloc. `--features rusty-alloc` swaps it for +// rusty_alloc (pure-Rust mimalloc v2.4.5 remake, #5872); the default build +// is unchanged. +#[cfg(not(feature = "rusty-alloc"))] #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +#[cfg(feature = "rusty-alloc")] +#[global_allocator] +static GLOBAL: rusty_alloc_api::RustyAlloc = rusty_alloc_api::RustyAlloc; + fn main() -> std::process::ExitCode { // Reset SIGPIPE to SIG_DFL so piping codewhale output into a command that // exits early (e.g. `codewhale doctor | head`) terminates the process diff --git a/crates/tui/CHANGELOG.md b/crates/tui/CHANGELOG.md index 47025c6680..b1da532da9 100644 --- a/crates/tui/CHANGELOG.md +++ b/crates/tui/CHANGELOG.md @@ -48,6 +48,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- The `rusty-alloc` cargo feature on `codewhale-tui` and `codewhale-cli` + opts the binaries into the `rusty_alloc` global allocator (the mimalloc + v2.4.5 architecture remade in pure Rust — no C compiler or build script + on that path) instead of the default mimalloc. It is off by default and + the default build is unchanged; build with + `cargo build -p codewhale-tui --features rusty-alloc` (#5872). - The `/theme` picker now discovers valid user-authored `custom:` overlays, previews their colors, highlights the active overlay, and preserves it when the picker is opened and committed without navigation (#5901). diff --git a/crates/tui/Cargo.toml b/crates/tui/Cargo.toml index 08a6ae5000..15a92b419f 100644 --- a/crates/tui/Cargo.toml +++ b/crates/tui/Cargo.toml @@ -14,6 +14,11 @@ workspace = true [features] default = [] long-running-tests = [] +# Opt-in global-allocator swap (#5872): build on rusty_alloc (the pure-Rust +# mimalloc v2.4.5 remake — no C compiler, no build script) instead of the +# default mimalloc. Off by default; the default build is unchanged. +# Build with: cargo build -p codewhale-tui --features rusty-alloc +rusty-alloc = ["dep:rusty_alloc-api"] [lib] name = "codewhale_tui" @@ -104,6 +109,7 @@ semver.workspace = true rust-i18n = "4.1.0" shell-words = "1.1.1" mimalloc.workspace = true +rusty_alloc-api = { workspace = true, optional = true } [build-dependencies] codewhale-build-support = { path = "../build-support", version = "0.9.12" } diff --git a/crates/tui/src/main.rs b/crates/tui/src/main.rs index b7404bd676..35a80d6c84 100644 --- a/crates/tui/src/main.rs +++ b/crates/tui/src/main.rs @@ -1,6 +1,14 @@ +// Default allocator: mimalloc. `--features rusty-alloc` swaps it for +// rusty_alloc (pure-Rust mimalloc v2.4.5 remake, #5872); the default build +// is unchanged. +#[cfg(not(feature = "rusty-alloc"))] #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +#[cfg(feature = "rusty-alloc")] +#[global_allocator] +static GLOBAL: rusty_alloc_api::RustyAlloc = rusty_alloc_api::RustyAlloc; + fn main() -> std::process::ExitCode { codewhale_tui::run(std::env::args().collect()) } diff --git a/docs/BUILD_PERFORMANCE.md b/docs/BUILD_PERFORMANCE.md index 3c51ff6c33..21bf244403 100644 --- a/docs/BUILD_PERFORMANCE.md +++ b/docs/BUILD_PERFORMANCE.md @@ -33,7 +33,9 @@ Structural facts behind those numbers: no default features). `cargo tree -d` shows only routine duplicates (`toml` 0.8/1.1, `thiserror` 1/2, `strum` 0.27/0.28, `syn` 2/3, `sha2` 0.10/0.11) that come from third-party crates, not from workspace - choices. + choices. The global allocator is mimalloc by default; the off-by-default + `rusty-alloc` cargo feature on `codewhale-tui`/`codewhale-cli` swaps it for + the pure-Rust `rusty_alloc` remake (no C toolchain on that path, #5872). - `[profile.dev] debug = "line-tables-only"` is already set (#5246) and Cargo already uses `split-debuginfo = unpacked` on macOS. - `target/debug` grows past 50 GB only through accumulation across diff --git a/web/lib/changelog.generated.ts b/web/lib/changelog.generated.ts index b86819124e..085462ac03 100644 --- a/web/lib/changelog.generated.ts +++ b/web/lib/changelog.generated.ts @@ -47,6 +47,7 @@ export const CHANGELOG: ChangelogRelease[] = [ { "heading": "Added", "items": [ + "The rusty-alloc cargo feature on codewhale-tui and codewhale-cli opts the binaries into the rusty_alloc global allocator (the mimalloc v2.4.5 architecture remade in pure Rust — no C compiler or build script on that path) instead of the default mimalloc. It is off by default and the default build is unchanged; build with cargo build -p codewhale-tui --features rusty-alloc (#5872).", "The /theme picker now discovers valid user-authored custom: overlays, previews their colors, highlights the active overlay, and preserves it when the picker is opened and committed without navigation (#5901).", "Compaction has two standing knobs next to [context] in config.toml: [compaction] summary_instructions (appended to the summarizer prompt on every manual and automatic pass; /compact still composes after it) and [compaction] retained_user_message_tokens (default 20 000, clamped 2 000..=200 000) for the verbatim user-message budget. Both are absent by default and absent means the pre-existing behavior. The /compact receipt names the effective budget and whether…", "[tools] user_input_max_questions (default 6, 1..=10) and [tools] user_input_max_options (default 4, 2..=10) replace the hard-coded request_user_input limits; the validator, the tool schema and its description read one value, spawned children inherit the parent's ceilings, and a rejected payload names the ceiling it hit and the key to raise (#5949).", @@ -57,10 +58,9 @@ export const CHANGELOG: ChangelogRelease[] = [ "codewhale account api-keys create --scope now accepts models:infer alongside account:read and agent:run, and an omitted --scope sends all three explicitly. --use saves the new secret as this machine's local codewhale provider credential in the same secret store codewhale auth uses; nothing is uploaded.", "sandbox_backend = \"shannon\": shell commands run as signed ShannonNet capability invocations (cap://sandbox/exec) on a worker that may live on another tailnet node. Codewhale opens a Task World per session for its durable codewhale Agent and every command leaves a receipt in shannon trace. New keys sandbox_shannon_home and sandbox_shannon_capability; tool metadata now reports the actual external backend kind instead of always opensandbox.", "/shannon [world|trace|children] inspects the session's ShannonNet World: agent, projected capabilities, children, and receipts.", - "ShannonNet sub-agents get compiled context: the session's native-memory hits are imported with provenance and the child's projected World decides what it sees (confidential notes never cross); the session World is checkpointed and closed when the backend drops.", - "Sub-agents under delegated authority: with the ShannonNet backend the agent tool spawns a child identity with a World projected from the session World, the child's shell commands are signed as that child, and a join receipt is recorded when it finishes. SandboxBackend::for_child / child_joined default to sharing the parent backend for other backends." + "ShannonNet sub-agents get compiled context: the session's native-memory hits are imported with provenance and the child's projected World decides what it sees (confidential notes never cross); the session World is checkpointed and closed when the backend drops." ], - "itemCount": 13 + "itemCount": 14 } ] },