From 05bb6b596efe194e00e84fea45bd271f76fc4aa5 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Wed, 29 Jul 2026 14:55:42 +0000 Subject: [PATCH 1/3] Use jemalloc allocator on non-MSVC targets --- CHANGELOG.md | 10 ++++++++++ Cargo.lock | 21 +++++++++++++++++++++ Cargo.toml | 3 +++ docs/decisions.md | 23 +++++++++++++++++++++++ src/main.rs | 7 +++++++ 5 files changed, 64 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8764ba9..335576a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,16 @@ Pre-1.0, the public API and the CLI surface may change in any release. Decisions and their rationale — including what was rejected — live in [`docs/decisions.md`](docs/decisions.md); this file records what shipped. +## [Unreleased] + +### Changed + +- **Non-MSVC builds use the pinned `tikv-jemallocator` 0.7.0 global + allocator.** The allocator is excluded from MSVC builds so the Windows CI + target keeps its existing toolchain path. The prior kubernetes measurement + recorded in the decision log showed lower RSS and wall time with jemalloc; + the stream's review and gate stages must re-run that measurement. + ## [0.0.2] - 2026-07-29 ### Added diff --git a/Cargo.lock b/Cargo.lock index abd1ecc..7379057 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,6 +87,7 @@ dependencies = [ "redb", "serde_json", "tempfile", + "tikv-jemallocator", "toml", ] @@ -767,6 +768,26 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "tikv-jemalloc-sys" +version = "0.7.1+5.3.1-0-g81034ce1f1373e37dc865038e1bc8eeecf559ce8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a2825c78386b4ae0314074867860ba9577875de945f05992c38815cbec327f0" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "tikv-jemallocator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "249f09e49ab1609436f34c776e84231bead18d6a955f119f939bdc1d847561bd" +dependencies = [ + "libc", + "tikv-jemalloc-sys", +] + [[package]] name = "toml" version = "1.1.2+spec-1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 057a57a..90f7669 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,9 @@ redb = "=4.1.0" serde_json = "1" toml = { version = "1", default-features = false, features = ["parse", "serde"] } +[target.'cfg(not(target_env = "msvc"))'.dependencies] +tikv-jemallocator = "=0.7.0" + [lints.rust] missing_docs = "deny" diff --git a/docs/decisions.md b/docs/decisions.md index e33560b..d6b2139 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -4,6 +4,29 @@ Newest first. Each entry records what was decided, why, and what was rejected. --- +## 2026-07-29 — jemalloc is the non-MSVC global allocator + +`tikv-jemallocator` **0.7.0** is pinned exactly for non-MSVC targets and +installed as the process global allocator. The crate's current docs list 0.7.0 +as the latest release, document the `#[global_allocator]` setup used here, and +license it under MIT or Apache-2.0. Its normal dependency footprint is +`libc` plus `tikv-jemalloc-sys`; no non-default allocator features are +enabled (the crate's default background-thread support remains enabled). +The MSVC cfg follows the crate's documented setup and keeps the dependency and +allocator declaration out of that target's build path. + +The choice is grounded in the previously recorded kubernetes measurement: the +existing decision log measured jemalloc at 793,548 kB / 63.6 s versus +832,740 kB / 70.6 s for the then-current allocator, with byte-identical output. +This stream does not claim to have re-run that heavyweight measurement; the +review and gate stages must verify it on the reference 2-vCPU environment. + +*Rejected: doing nothing.* The measured RSS and wall reductions recover +headroom and timing margin for a one-line allocator choice, while the target +cfg limits the portability risk to platforms where the crate is supported. + +--- + ## 2026-07-29 — the walk keeps a file's declarations and forgets its references Wave 2 taught Go to emit type uses, non-call selector reads and diff --git a/src/main.rs b/src/main.rs index ea5da5d..b95021d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,13 @@ use std::path::{Path, PathBuf}; use std::process::ExitCode; +#[cfg(not(target_env = "msvc"))] +use tikv_jemallocator::Jemalloc; + +#[cfg(not(target_env = "msvc"))] +#[global_allocator] +static GLOBAL: Jemalloc = Jemalloc; + use clap::{Parser, Subcommand}; use arthron::config::Config; From 62318ca9ef9a58a454ac49412f69ab0962a9ade9 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Wed, 29 Jul 2026 15:53:44 +0000 Subject: [PATCH 2/3] Reject jemalloc after measured RSS regression --- CHANGELOG.md | 10 ---------- Cargo.lock | 21 --------------------- Cargo.toml | 3 --- docs/decisions.md | 23 ----------------------- src/main.rs | 7 ------- 5 files changed, 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 335576a..8764ba9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,16 +9,6 @@ Pre-1.0, the public API and the CLI surface may change in any release. Decisions and their rationale — including what was rejected — live in [`docs/decisions.md`](docs/decisions.md); this file records what shipped. -## [Unreleased] - -### Changed - -- **Non-MSVC builds use the pinned `tikv-jemallocator` 0.7.0 global - allocator.** The allocator is excluded from MSVC builds so the Windows CI - target keeps its existing toolchain path. The prior kubernetes measurement - recorded in the decision log showed lower RSS and wall time with jemalloc; - the stream's review and gate stages must re-run that measurement. - ## [0.0.2] - 2026-07-29 ### Added diff --git a/Cargo.lock b/Cargo.lock index 7379057..abd1ecc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,7 +87,6 @@ dependencies = [ "redb", "serde_json", "tempfile", - "tikv-jemallocator", "toml", ] @@ -768,26 +767,6 @@ dependencies = [ "syn 3.0.3", ] -[[package]] -name = "tikv-jemalloc-sys" -version = "0.7.1+5.3.1-0-g81034ce1f1373e37dc865038e1bc8eeecf559ce8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a2825c78386b4ae0314074867860ba9577875de945f05992c38815cbec327f0" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "tikv-jemallocator" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "249f09e49ab1609436f34c776e84231bead18d6a955f119f939bdc1d847561bd" -dependencies = [ - "libc", - "tikv-jemalloc-sys", -] - [[package]] name = "toml" version = "1.1.2+spec-1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 90f7669..057a57a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,9 +46,6 @@ redb = "=4.1.0" serde_json = "1" toml = { version = "1", default-features = false, features = ["parse", "serde"] } -[target.'cfg(not(target_env = "msvc"))'.dependencies] -tikv-jemallocator = "=0.7.0" - [lints.rust] missing_docs = "deny" diff --git a/docs/decisions.md b/docs/decisions.md index d6b2139..e33560b 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -4,29 +4,6 @@ Newest first. Each entry records what was decided, why, and what was rejected. --- -## 2026-07-29 — jemalloc is the non-MSVC global allocator - -`tikv-jemallocator` **0.7.0** is pinned exactly for non-MSVC targets and -installed as the process global allocator. The crate's current docs list 0.7.0 -as the latest release, document the `#[global_allocator]` setup used here, and -license it under MIT or Apache-2.0. Its normal dependency footprint is -`libc` plus `tikv-jemalloc-sys`; no non-default allocator features are -enabled (the crate's default background-thread support remains enabled). -The MSVC cfg follows the crate's documented setup and keeps the dependency and -allocator declaration out of that target's build path. - -The choice is grounded in the previously recorded kubernetes measurement: the -existing decision log measured jemalloc at 793,548 kB / 63.6 s versus -832,740 kB / 70.6 s for the then-current allocator, with byte-identical output. -This stream does not claim to have re-run that heavyweight measurement; the -review and gate stages must verify it on the reference 2-vCPU environment. - -*Rejected: doing nothing.* The measured RSS and wall reductions recover -headroom and timing margin for a one-line allocator choice, while the target -cfg limits the portability risk to platforms where the crate is supported. - ---- - ## 2026-07-29 — the walk keeps a file's declarations and forgets its references Wave 2 taught Go to emit type uses, non-call selector reads and diff --git a/src/main.rs b/src/main.rs index b95021d..ea5da5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,13 +27,6 @@ use std::path::{Path, PathBuf}; use std::process::ExitCode; -#[cfg(not(target_env = "msvc"))] -use tikv_jemallocator::Jemalloc; - -#[cfg(not(target_env = "msvc"))] -#[global_allocator] -static GLOBAL: Jemalloc = Jemalloc; - use clap::{Parser, Subcommand}; use arthron::config::Config; From dde621ffbb16f0ec69adcf7e0b0966c76d9a3f0f Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Thu, 30 Jul 2026 08:21:17 +0000 Subject: [PATCH 3/3] Document post-#55 jemalloc rejection --- docs/decisions.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/docs/decisions.md b/docs/decisions.md index 5915057..4ba317b 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -4,6 +4,47 @@ Newest first. Each entry records what was decided, why, and what was rejected. --- +## 2026-07-30 — jemalloc is rejected on the post-#55 reference build + +**Decided: keep the system allocator.** Stream A measured the non-MSVC +`tikv-jemallocator` 0.7.0 build (`05bb6b5`) against its parent +`035821a` on the read-only Kubernetes tree at +`7fbcad5e8ec387e23061602eb2d4b110b049410c` (17,873 Go files, +5,353,211 lines). Both release binaries ran three cold scans with one clean +store per run under `taskset -c 0,1` and `/usr/bin/time -v`; no cargo, rustc, +or arthron process was live before the batch. + +| build | cold wall (s) | peak RSS (kB) | median wall / RSS | +|---|---|---|---| +| system allocator | 132.20, 135.66, 122.42 | 285,832, 285,324, 284,296 | 132.20 / 285,324 | +| jemalloc | 123.33, 115.65, 101.82 | 322,504, 313,964, 320,808 | 115.65 / 320,808 | + +Jemalloc improved median wall time by 16.55 seconds (12.52%), but increased +median peak RSS by 35,484 kB (12.44%). The acceptance requires both metrics to +improve or hold, so the RSS regression rejects the allocator. All six stores +had the same SHA256, +`e9b6c3e4633e3aa99054d3b2a4e8c26e9cf7505ba4a1b30aa3c620cf31ad955b`; +the result is a resource regression, not a graph difference. Three Flask cold +runs also had higher jemalloc RSS. + +This does not erase the earlier 793,548 kB / 63.6 s versus 832,740 kB / +70.6 s measurement below. That comparison was taken before #55 changed the +walk's retained-reference memory model, whereas this one is against the +post-#55 285 MB baseline. The measurements therefore do not describe the same +binary memory model; this record makes no unmeasured claim that their corpora +differed. The N-033 ruling requires Stream B to re-measure both allocators on +the pinned Node tree before its final RSS gate. + +*Rejected: carrying the older jemalloc result forward as a current claim.* Its +code footing predates the structural change that changed the observed allocator +behavior. A past saving is evidence to re-measure, not permission to ignore a +current regression. + +*Rejected: landing jemalloc for wall time alone.* The cold-RSS ceiling is hard; +the time target cannot trade it away. + +--- + ## 2026-07-30 — Stream C's Java measurements are rebased with attributed aliases **Decided: rebase the two Java baselines and target pins from the signed