diff --git a/Cargo.lock b/Cargo.lock index fd0ef478c..88a510f37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9235,6 +9235,7 @@ dependencies = [ "rustfs-log-analyzer", "rustfs-madmin", "rustfs-mimalloc", + "rustfs-mimalloc-sys", "rustfs-notify", "rustfs-object-capacity", "rustfs-object-data-cache", @@ -9273,7 +9274,6 @@ dependencies = [ "temp-env", "tempfile", "thiserror 2.0.20", - "tikv-jemallocator", "time", "tokio", "tokio-rustls", @@ -11999,26 +11999,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "tikv-jemalloc-sys" -version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "tikv-jemallocator" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a" -dependencies = [ - "libc", - "tikv-jemalloc-sys", -] - [[package]] name = "time" version = "0.3.55" diff --git a/Cargo.toml b/Cargo.toml index 3a3b8c5d6..026cebb43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -210,6 +210,7 @@ sha1 = "0.11.0" sha2 = "0.11.0" subtle = "2.6" zeroize = { version = "1.9.0" } +proptest = "1" # Time and Date chrono = { version = "0.4.45" } @@ -352,6 +353,7 @@ dav-server = "0.11.0" # Performance Analysis and Memory Profiling rustfs-mimalloc = { version = "0.5.0" } +rustfs-mimalloc-sys = { version = "0.5.0" } hotpath = { version = "0.24.0", default-features = false } # Snapshot testing for output format regression detection insta = { version = "1.48" } diff --git a/crates/heal/src/lib.rs b/crates/heal/src/lib.rs index a60946229..7b91df47a 100644 --- a/crates/heal/src/lib.rs +++ b/crates/heal/src/lib.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![recursion_limit = "256"] + mod error; pub mod heal; diff --git a/crates/heal/tests/mrf_pipeline_test.rs b/crates/heal/tests/mrf_pipeline_test.rs index 2fdb4603f..a1b9ee502 100644 --- a/crates/heal/tests/mrf_pipeline_test.rs +++ b/crates/heal/tests/mrf_pipeline_test.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![recursion_limit = "256"] + //! HS-01 (rustfs/backlog#1865): MRF intent pipeline integration tests. //! //! Drives the real consumer loop (`spawn_mrf_consumer`) against a real diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index 5220a16ff..30fb499ba 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -56,9 +56,6 @@ rio-v2 = ["rustfs-ecstore/rio-v2"] pyroscope = ["rustfs-obs/pyroscope"] # Tokio runtime telemetry. Requires `--cfg tokio_unstable`; use `make build-profiling`. dial9 = ["rustfs-obs/dial9"] -# Allocator features -mimalloc = ["dep:rustfs-mimalloc"] -jemalloc = ["dep:tikv-jemallocator"] hotpath = [ "hotpath/hotpath", "hotpath/tokio", @@ -339,13 +336,13 @@ opentelemetry = { workspace = true } tracing-opentelemetry = { workspace = true } # Data structures hashbrown = { workspace = true, features = ["serde", "rayon"] } -rustfs-mimalloc = { workspace = true, optional = true } +rustfs-mimalloc = { workspace = true } [target.'cfg(target_os = "linux")'.dependencies] libsystemd.workspace = true [target.'cfg(not(target_os = "windows"))'.dependencies] -tikv-jemallocator = { version = "0.6", optional = true } +rustfs-mimalloc-sys = { workspace = true } [dev-dependencies] uuid = { workspace = true, features = ["v4", "v5", "fast-rng", "macro-diagnostics"] } @@ -354,7 +351,7 @@ tempfile = { workspace = true } aws-config = { workspace = true } anyhow = { workspace = true } insta = { workspace = true, features = ["yaml", "json"] } -proptest = "1" +proptest = { workspace = true } tokio = { workspace = true, features = ["test-util", "fs", "rt-multi-thread"] } temp-env = { workspace = true, features = ["async_closure"] } tracing-subscriber = { workspace = true, features = ["env-filter", "time"] } diff --git a/rustfs/src/allocator_reclaim.rs b/rustfs/src/allocator_reclaim.rs index 980fc2abe..5c2853de2 100644 --- a/rustfs/src/allocator_reclaim.rs +++ b/rustfs/src/allocator_reclaim.rs @@ -169,25 +169,15 @@ impl AllocatorReclaimController { /// Return the allocator backend name used by reclaim and memory metrics. pub fn allocator_backend() -> &'static str { - #[cfg(all(feature = "mimalloc", not(target_os = "windows")))] + #[cfg(not(target_os = "windows"))] { "mimalloc" } - #[cfg(all(feature = "mimalloc", target_os = "windows"))] + #[cfg(target_os = "windows")] { "mimalloc-windows" } - - #[cfg(all(not(feature = "mimalloc"), feature = "jemalloc"))] - { - "jemalloc" - } - - #[cfg(not(any(feature = "mimalloc", feature = "jemalloc")))] - { - "system" - } } fn active_requests() -> u64 { @@ -378,13 +368,13 @@ pub fn allocator_reclaim_controller_snapshot(ctx: &CancellationToken) -> Allocat ) } -#[cfg(all(feature = "mimalloc", not(target_os = "windows")))] +#[cfg(not(target_os = "windows"))] fn collect_allocator_memory(force: bool) -> Result<(), String> { rustfs_mimalloc::MiMalloc::collect(force); Ok(()) } -#[cfg(not(all(feature = "mimalloc", not(target_os = "windows"))))] +#[cfg(target_os = "windows")] fn collect_allocator_memory(_force: bool) -> Result<(), String> { Err("allocator reclaim requires mimalloc on a non-Windows target".to_string()) } diff --git a/rustfs/src/lib.rs b/rustfs/src/lib.rs index e4316aa01..a1836f4f3 100644 --- a/rustfs/src/lib.rs +++ b/rustfs/src/lib.rs @@ -52,11 +52,6 @@ //! tests where you start one server in a background task, run all your //! tests, and then shut it down. -#[cfg(all(feature = "mimalloc", feature = "jemalloc"))] -compile_error!("allocator features 'mimalloc' and 'jemalloc' are mutually exclusive"); -#[cfg(all(feature = "jemalloc", target_os = "windows"))] -compile_error!("allocator feature 'jemalloc' is not supported on Windows"); - /// Scope-based hotpath measurement for `#[async_trait]` methods, where /// `#[hotpath::measure]` would only time the boxed-future construction. /// The guard records wall time from this statement until the enclosing diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index a0b60321a..20df64458 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -12,29 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[cfg(all( - feature = "hotpath", - feature = "hotpath-alloc", - feature = "mimalloc", - not(feature = "jemalloc") -))] +#[cfg(all(feature = "hotpath", feature = "hotpath-alloc", not(target_os = "windows")))] use std::alloc::{GlobalAlloc, Layout}; -#[cfg(all( - feature = "hotpath", - feature = "hotpath-alloc", - feature = "mimalloc", - not(feature = "jemalloc") -))] +#[cfg(all(feature = "hotpath", feature = "hotpath-alloc", not(target_os = "windows")))] #[derive(Default)] struct MiMallocAllocator; -#[cfg(all( - feature = "hotpath", - feature = "hotpath-alloc", - feature = "mimalloc", - not(feature = "jemalloc") -))] +#[cfg(all(feature = "hotpath", feature = "hotpath-alloc", not(target_os = "windows")))] // SAFETY: allocation operations are forwarded unchanged to MiMalloc, so // MiMalloc's GlobalAlloc guarantees apply to every returned pointer and layout. #[allow(unsafe_code)] @@ -60,65 +45,25 @@ unsafe impl GlobalAlloc for MiMallocAllocator { } } -#[cfg(all( - feature = "hotpath", - feature = "hotpath-alloc", - feature = "mimalloc", - not(feature = "jemalloc") -))] +#[cfg(all(feature = "hotpath", feature = "hotpath-alloc", not(target_os = "windows")))] #[global_allocator] static GLOBAL: hotpath::CountingAllocator = hotpath::CountingAllocator::with(MiMallocAllocator); -#[cfg(all( - feature = "hotpath", - feature = "hotpath-alloc", - feature = "jemalloc", - not(feature = "mimalloc"), - not(target_os = "windows") -))] -#[global_allocator] -static GLOBAL: hotpath::CountingAllocator = - hotpath::CountingAllocator::with(tikv_jemallocator::Jemalloc); - -#[cfg(all( - feature = "hotpath", - feature = "hotpath-alloc", - not(any(feature = "mimalloc", feature = "jemalloc")) -))] +#[cfg(all(feature = "hotpath", feature = "hotpath-alloc", target_os = "windows"))] #[global_allocator] static GLOBAL: hotpath::CountingAllocator = hotpath::CountingAllocator::with(std::alloc::System); -#[cfg(all( - not(all(feature = "hotpath", feature = "hotpath-alloc")), - feature = "mimalloc", - not(feature = "jemalloc") -))] +#[cfg(all(not(all(feature = "hotpath", feature = "hotpath-alloc")), not(target_os = "windows")))] #[global_allocator] static GLOBAL: rustfs_mimalloc::MiMalloc = rustfs_mimalloc::MiMalloc; -#[cfg(all( - not(all(feature = "hotpath", feature = "hotpath-alloc")), - feature = "jemalloc", - not(feature = "mimalloc"), - not(target_os = "windows") -))] -#[global_allocator] -static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; - fn main() { let _hotpath_guard = hotpath::HotpathGuardBuilder::new("main").build(); rustfs::startup_entrypoint::run_process(); } -#[cfg(all( - test, - feature = "hotpath", - feature = "hotpath-alloc", - feature = "mimalloc", - not(feature = "jemalloc"), - not(target_os = "windows") -))] +#[cfg(all(test, feature = "hotpath", feature = "hotpath-alloc", not(target_os = "windows")))] mod tests { #[test] // SAFETY: This test inspects a live allocation pointer with mimalloc's heap diff --git a/rustfs/src/memory_observability.rs b/rustfs/src/memory_observability.rs index ef2fc349d..44c64444f 100644 --- a/rustfs/src/memory_observability.rs +++ b/rustfs/src/memory_observability.rs @@ -17,7 +17,7 @@ use rustfs_io_metrics::{ record_cpu_usage, record_memory_usage, record_process_memory_split, }; use serde::Serialize; -#[cfg(any(feature = "mimalloc", test))] +#[cfg(any(not(target_os = "windows"), test))] use serde_json::Value; use std::path::Path; use std::sync::{Arc, Mutex, OnceLock}; @@ -229,7 +229,7 @@ fn read_cgroup_memory_snapshot() -> Option { read_cgroup_v2().or_else(read_cgroup_v1) } -#[cfg(feature = "mimalloc")] +#[cfg(not(target_os = "windows"))] fn read_allocator_memory_snapshot() -> Option { let json = rustfs_mimalloc::MiMalloc::stats_json(); if json.is_empty() { @@ -242,12 +242,12 @@ fn read_allocator_memory_snapshot() -> Option { }) } -#[cfg(not(feature = "mimalloc"))] +#[cfg(target_os = "windows")] fn read_allocator_memory_snapshot() -> Option { None } -#[cfg(any(feature = "mimalloc", test))] +#[cfg(any(not(target_os = "windows"), test))] fn numeric_json_value(value: &Value) -> Option { match value { Value::Number(number) => number @@ -258,7 +258,7 @@ fn numeric_json_value(value: &Value) -> Option { } } -#[cfg(any(feature = "mimalloc", test))] +#[cfg(any(not(target_os = "windows"), test))] fn numeric_json_field(value: &Value, field: &str) -> Option { match value { Value::Object(fields) => fields @@ -270,7 +270,7 @@ fn numeric_json_field(value: &Value, field: &str) -> Option { } } -#[cfg(any(feature = "mimalloc", test))] +#[cfg(any(not(target_os = "windows"), test))] fn mimalloc_stat_field(value: &Value, metric: &str, field: &str) -> Option { match value { Value::Object(fields) => { @@ -287,12 +287,12 @@ fn mimalloc_stat_field(value: &Value, metric: &str, field: &str) -> Option } } -#[cfg(any(feature = "mimalloc", test))] +#[cfg(any(not(target_os = "windows"), test))] fn mimalloc_stat_current(value: &Value, metric: &str) -> Option { mimalloc_stat_field(value, metric, "current") } -#[cfg(any(feature = "mimalloc", test))] +#[cfg(any(not(target_os = "windows"), test))] fn mimalloc_stat_sum(value: &Value, metrics: &[&str], field: &str) -> Option { metrics .iter() @@ -301,7 +301,7 @@ fn mimalloc_stat_sum(value: &Value, metrics: &[&str], field: &str) -> Option 0) } -#[cfg(any(feature = "mimalloc", test))] +#[cfg(any(not(target_os = "windows"), test))] fn parse_mimalloc_stats_json(stats_json: &str) -> Option { let value = serde_json::from_str::(stats_json).ok()?; let malloc_metrics = ["malloc_normal", "malloc_huge"]; @@ -558,9 +558,9 @@ mod tests { #[test] fn read_allocator_memory_snapshot_uses_mimalloc_stats_json() { let snapshot = super::read_allocator_memory_snapshot(); - #[cfg(all(feature = "mimalloc", not(target_os = "windows")))] + #[cfg(not(target_os = "windows"))] assert!(snapshot.is_some(), "allocator snapshot should be available on non-Windows"); - #[cfg(not(feature = "mimalloc"))] + #[cfg(target_os = "windows")] assert!(snapshot.is_none(), "allocator snapshot should be absent without mimalloc"); }