mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-03 00:31:50 +00:00
Switch allocator to jemalloc (#3697)
## Proposed Changes Another `tree-states` motivated PR, this adds `jemalloc` as the default allocator, with an option to use the system allocator by compiling with `FEATURES="" make`. - [x] Metrics - [x] Test on Windows - [x] Test on macOS - [x] Test with `musl` - [x] Metrics dashboard on `lighthouse-metrics` (https://github.com/sigp/lighthouse-metrics/pull/37) Co-authored-by: Michael Sproul <micsproul@gmail.com>
This commit is contained in:
@@ -4,13 +4,21 @@ version = "0.1.0"
|
||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lighthouse_metrics = { path = "../lighthouse_metrics" }
|
||||
lazy_static = "1.4.0"
|
||||
libc = "0.2.79"
|
||||
parking_lot = "0.12.0"
|
||||
jemalloc-ctl = { version = "0.5.0", optional = true }
|
||||
|
||||
# Jemalloc's background_threads feature requires Linux (pthreads).
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
jemallocator = { version = "0.5.0", optional = true, features = ["stats", "background_threads"] }
|
||||
|
||||
[target.'cfg(not(target_os = "linux"))'.dependencies]
|
||||
jemallocator = { version = "0.5.0", optional = true, features = ["stats"] }
|
||||
|
||||
[features]
|
||||
mallinfo2 = []
|
||||
jemalloc = ["jemallocator", "jemalloc-ctl"]
|
||||
jemalloc-profiling = ["jemallocator/profiling"]
|
||||
|
||||
52
common/malloc_utils/src/jemalloc.rs
Normal file
52
common/malloc_utils/src/jemalloc.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
//! Set the allocator to `jemalloc`.
|
||||
//!
|
||||
//! Due to `jemalloc` requiring configuration at compile time or immediately upon runtime
|
||||
//! initialisation it is configured via a Cargo config file in `.cargo/config.toml`.
|
||||
//!
|
||||
//! The `jemalloc` tuning can be overriden by:
|
||||
//!
|
||||
//! A) `JEMALLOC_SYS_WITH_MALLOC_CONF` at compile-time.
|
||||
//! B) `_RJEM_MALLOC_CONF` at runtime.
|
||||
use jemalloc_ctl::{arenas, epoch, stats, Error};
|
||||
use lazy_static::lazy_static;
|
||||
use lighthouse_metrics::{set_gauge, try_create_int_gauge, IntGauge};
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
|
||||
|
||||
// Metrics for jemalloc.
|
||||
lazy_static! {
|
||||
pub static ref NUM_ARENAS: lighthouse_metrics::Result<IntGauge> =
|
||||
try_create_int_gauge("jemalloc_num_arenas", "The number of arenas in use");
|
||||
pub static ref BYTES_ALLOCATED: lighthouse_metrics::Result<IntGauge> =
|
||||
try_create_int_gauge("jemalloc_bytes_allocated", "Equivalent to stats.allocated");
|
||||
pub static ref BYTES_ACTIVE: lighthouse_metrics::Result<IntGauge> =
|
||||
try_create_int_gauge("jemalloc_bytes_active", "Equivalent to stats.active");
|
||||
pub static ref BYTES_MAPPED: lighthouse_metrics::Result<IntGauge> =
|
||||
try_create_int_gauge("jemalloc_bytes_mapped", "Equivalent to stats.mapped");
|
||||
pub static ref BYTES_METADATA: lighthouse_metrics::Result<IntGauge> =
|
||||
try_create_int_gauge("jemalloc_bytes_metadata", "Equivalent to stats.metadata");
|
||||
pub static ref BYTES_RESIDENT: lighthouse_metrics::Result<IntGauge> =
|
||||
try_create_int_gauge("jemalloc_bytes_resident", "Equivalent to stats.resident");
|
||||
pub static ref BYTES_RETAINED: lighthouse_metrics::Result<IntGauge> =
|
||||
try_create_int_gauge("jemalloc_bytes_retained", "Equivalent to stats.retained");
|
||||
}
|
||||
|
||||
pub fn scrape_jemalloc_metrics() {
|
||||
scrape_jemalloc_metrics_fallible().unwrap()
|
||||
}
|
||||
|
||||
pub fn scrape_jemalloc_metrics_fallible() -> Result<(), Error> {
|
||||
// Advance the epoch so that the underlying statistics are updated.
|
||||
epoch::advance()?;
|
||||
|
||||
set_gauge(&NUM_ARENAS, arenas::narenas::read()? as i64);
|
||||
set_gauge(&BYTES_ALLOCATED, stats::allocated::read()? as i64);
|
||||
set_gauge(&BYTES_ACTIVE, stats::active::read()? as i64);
|
||||
set_gauge(&BYTES_MAPPED, stats::mapped::read()? as i64);
|
||||
set_gauge(&BYTES_METADATA, stats::metadata::read()? as i64);
|
||||
set_gauge(&BYTES_RESIDENT, stats::resident::read()? as i64);
|
||||
set_gauge(&BYTES_RETAINED, stats::retained::read()? as i64);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -2,18 +2,18 @@
|
||||
//!
|
||||
//! ## Conditional Compilation
|
||||
//!
|
||||
//! Presently, only configuration for "The GNU Allocator" from `glibc` is supported. All other
|
||||
//! allocators are ignored.
|
||||
//! This crate can be compiled with different feature flags to support different allocators:
|
||||
//!
|
||||
//! It is assumed that if the following two statements are correct then we should expect to
|
||||
//! configure `glibc`:
|
||||
//! - Jemalloc, via the `jemalloc` feature.
|
||||
//! - GNU malloc, if no features are set and the system supports it.
|
||||
//! - The system allocator, if no features are set and the allocator is not GNU malloc.
|
||||
//!
|
||||
//! It is assumed that if Jemalloc is not in use, and the following two statements are correct then
|
||||
//! we should expect to configure `glibc`:
|
||||
//!
|
||||
//! - `target_os = linux`
|
||||
//! - `target_env != musl`
|
||||
//!
|
||||
//! In all other cases this library will not attempt to do anything (i.e., all functions are
|
||||
//! no-ops).
|
||||
//!
|
||||
//! If the above conditions are fulfilled but `glibc` still isn't present at runtime then a panic
|
||||
//! may be triggered. It is understood that there's no way to be certain that a compatible `glibc`
|
||||
//! is present: https://github.com/rust-lang/rust/issues/33244.
|
||||
@@ -24,18 +24,42 @@
|
||||
//! detecting `glibc` are best-effort. If this crate throws errors about undefined external
|
||||
//! functions, then try to compile with the `not_glibc_interface` module.
|
||||
|
||||
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
not(target_env = "musl"),
|
||||
not(feature = "jemalloc")
|
||||
))]
|
||||
mod glibc;
|
||||
|
||||
#[cfg(feature = "jemalloc")]
|
||||
mod jemalloc;
|
||||
|
||||
pub use interface::*;
|
||||
|
||||
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
not(target_env = "musl"),
|
||||
not(feature = "jemalloc")
|
||||
))]
|
||||
mod interface {
|
||||
pub use crate::glibc::configure_glibc_malloc as configure_memory_allocator;
|
||||
pub use crate::glibc::scrape_mallinfo_metrics as scrape_allocator_metrics;
|
||||
}
|
||||
|
||||
#[cfg(any(not(target_os = "linux"), target_env = "musl"))]
|
||||
#[cfg(feature = "jemalloc")]
|
||||
mod interface {
|
||||
#[allow(dead_code)]
|
||||
pub fn configure_memory_allocator() -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub use crate::jemalloc::scrape_jemalloc_metrics as scrape_allocator_metrics;
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(not(target_os = "linux"), target_env = "musl"),
|
||||
not(feature = "jemalloc")
|
||||
))]
|
||||
mod interface {
|
||||
#[allow(dead_code, clippy::unnecessary_wraps)]
|
||||
pub fn configure_memory_allocator() -> Result<(), String> {
|
||||
|
||||
Reference in New Issue
Block a user