diff --git a/src/allocator.rs b/src/allocator.rs new file mode 100644 index 0000000..10f52d3 --- /dev/null +++ b/src/allocator.rs @@ -0,0 +1,28 @@ +//! the global allocator, picked by the `alloc-*` features. the hydrant binary and the benches +//! both include this file, so benchmarks allocate the way production does. + +#[cfg(feature = "alloc-mimalloc")] +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + +#[cfg(feature = "alloc-jemalloc")] +#[global_allocator] +static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; + +// bake the tuned jemalloc runtime config into the binary. the prefixed tikv build reads +// the `_rjem_malloc_conf` symbol (plain `malloc_conf` silently no-ops). `percpu_arena` +// pins one arena per cpu, bounding per-arena dirty-page retention — the dominant rss lever +// here (~2.4x less resident than the default 4*ncpu arenas); `background_thread` purges +// asynchronously so `dirty_decay_ms:1000`/`muzzy_decay_ms:0` return pages without sync +// munmap churn. measured 1.72 GiB steady vs 4.14 for mimalloc. both options are linux-only +// (they no-op or warn elsewhere), so gate to linux; other targets get vanilla jemalloc. +// overridable at runtime via _RJEM_MALLOC_CONF. +#[cfg(all(feature = "alloc-jemalloc", target_os = "linux"))] +#[allow(non_upper_case_globals)] +#[unsafe(export_name = "_rjem_malloc_conf")] +pub static _rjem_malloc_conf: Option<&'static core::ffi::CStr> = + Some(c"background_thread:true,percpu_arena:percpu,dirty_decay_ms:1000,muzzy_decay_ms:0"); + +#[cfg(feature = "alloc-snmalloc")] +#[global_allocator] +static GLOBAL: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc; diff --git a/src/main.rs b/src/main.rs index c924efd..a44924b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,8 @@ use hydrant::config::Config; use hydrant::control::{ApiBinds, Hydrant}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; +mod allocator; + const DEFAULT_API_PORT: u16 = 3000; const DEFAULT_DEBUG_PORT: u16 = DEFAULT_API_PORT + 1; @@ -58,32 +60,6 @@ fn parse_api_binds() -> miette::Result { .ok_or_else(|| miette::miette!("HYDRANT_API_BIND is set but contains no addresses")) } -#[cfg(feature = "alloc-mimalloc")] -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -#[cfg(feature = "alloc-jemalloc")] -#[global_allocator] -static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; - -// bake the tuned jemalloc runtime config into the binary. the prefixed tikv build reads -// the `_rjem_malloc_conf` symbol (plain `malloc_conf` silently no-ops). `percpu_arena` -// pins one arena per cpu, bounding per-arena dirty-page retention — the dominant rss lever -// here (~2.4x less resident than the default 4*ncpu arenas); `background_thread` purges -// asynchronously so `dirty_decay_ms:1000`/`muzzy_decay_ms:0` return pages without sync -// munmap churn. measured 1.72 GiB steady vs 4.14 for mimalloc. both options are linux-only -// (they no-op or warn elsewhere), so gate to linux; other targets get vanilla jemalloc. -// overridable at runtime via _RJEM_MALLOC_CONF. -#[cfg(all(feature = "alloc-jemalloc", target_os = "linux"))] -#[allow(non_upper_case_globals)] -#[unsafe(export_name = "_rjem_malloc_conf")] -pub static _rjem_malloc_conf: Option<&'static core::ffi::CStr> = - Some(c"background_thread:true,percpu_arena:percpu,dirty_decay_ms:1000,muzzy_decay_ms:0"); - -#[cfg(feature = "alloc-snmalloc")] -#[global_allocator] -static GLOBAL: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc; - #[tokio::main] async fn main() -> miette::Result<()> { rustls::crypto::aws_lc_rs::default_provider()