mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
feat: replace jemalloc with mimalloc (#4174)
* feat: replace jemalloc with mimalloc * docs: record allocator rounds5 retest * fix(replication): satisfy clippy unwrap lints * docs: keep allocator migration plan local only * feat(profiling): rely on pyroscope cpu profiling * refactor(profiling): centralize unsupported pprof responses * chore(deps): update s3s revision
This commit is contained in:
@@ -28,7 +28,7 @@ documentation = "https://docs.rs/rustfs-obs/latest/rustfs_obs/"
|
||||
[features]
|
||||
default = []
|
||||
gpu = ["dep:nvml-wrapper"]
|
||||
pyroscope = ["dep:jemalloc_pprof", "dep:pyroscope"]
|
||||
pyroscope = ["dep:pyroscope"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -83,7 +83,6 @@ nvml-wrapper = { workspace = true, optional = true }
|
||||
|
||||
[target.'cfg(any(target_os = "macos", all(target_os = "linux", target_env = "gnu", target_arch = "x86_64")))'.dependencies]
|
||||
pyroscope = { workspace = true, features = ["backend-pprof-rs"], optional = true }
|
||||
jemalloc_pprof = { workspace = true, optional = true }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -39,10 +39,6 @@ pub(crate) type ProfilingAgent = pyroscope::PyroscopeAgent<pyroscope::pyroscope:
|
||||
any(target_os = "macos", all(target_os = "linux", target_env = "gnu", target_arch = "x86_64"))
|
||||
)))]
|
||||
pub(crate) type ProfilingAgent = ();
|
||||
#[cfg(all(feature = "pyroscope", target_os = "linux", target_env = "gnu", target_arch = "x86_64"))]
|
||||
pub(crate) type MemoryProfilingAgent = pyroscope::PyroscopeAgent<pyroscope::pyroscope::PyroscopeAgentRunning>;
|
||||
#[cfg(not(all(feature = "pyroscope", target_os = "linux", target_env = "gnu", target_arch = "x86_64")))]
|
||||
pub(crate) type MemoryProfilingAgent = ();
|
||||
|
||||
const LOG_COMPONENT_OBS: &str = "obs";
|
||||
const LOG_SUBSYSTEM_GUARD: &str = "guard";
|
||||
@@ -67,7 +63,6 @@ pub struct OtelGuard {
|
||||
/// Optional logger provider for OTLP log export.
|
||||
pub(crate) logger_provider: Option<SdkLoggerProvider>,
|
||||
pub(crate) profiling_agent: Option<ProfilingAgent>,
|
||||
pub(crate) memory_profiling_agent: Option<MemoryProfilingAgent>,
|
||||
/// Handle to the background log-cleanup task; aborted on drop.
|
||||
pub(crate) cleanup_handle: Option<tokio::task::JoinHandle<()>>,
|
||||
/// Worker guard that keeps the non-blocking `tracing_appender` thread
|
||||
@@ -84,7 +79,6 @@ impl std::fmt::Debug for OtelGuard {
|
||||
.field("meter_provider", &self.meter_provider.is_some())
|
||||
.field("logger_provider", &self.logger_provider.is_some())
|
||||
.field("profiling_agent", &self.profiling_agent.is_some())
|
||||
.field("memory_profiling_agent", &self.memory_profiling_agent.is_some())
|
||||
.field("cleanup_handle", &self.cleanup_handle.is_some())
|
||||
.field("tracing_guard", &self.tracing_guard.is_some())
|
||||
.field("stdout_guard", &self.stdout_guard.is_some())
|
||||
@@ -161,30 +155,6 @@ impl Drop for OtelGuard {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "pyroscope", target_os = "linux", target_env = "gnu", target_arch = "x86_64"))]
|
||||
if let Some(agent) = self.memory_profiling_agent.take() {
|
||||
match agent.stop() {
|
||||
Err(err) => {
|
||||
if tracing::dispatcher::has_been_set() {
|
||||
error!(
|
||||
event = EVENT_OBS_GUARD_SHUTDOWN,
|
||||
component = LOG_COMPONENT_OBS,
|
||||
subsystem = LOG_SUBSYSTEM_GUARD,
|
||||
resource = "memory_profiling_agent",
|
||||
result = "shutdown_failed",
|
||||
error = %err,
|
||||
"observability guard shutdown failed"
|
||||
);
|
||||
} else {
|
||||
eprintln!("{}", format_guard_shutdown_stderr_message("memory_profiling_agent", err));
|
||||
}
|
||||
}
|
||||
Ok(stopped) => {
|
||||
stopped.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(handle) = self.cleanup_handle.take() {
|
||||
debug!(
|
||||
event = EVENT_OBS_GUARD_SHUTDOWN,
|
||||
|
||||
@@ -271,7 +271,6 @@ fn init_stdout_only(_config: &OtelConfig, logger_level: &str, is_production: boo
|
||||
meter_provider: None,
|
||||
logger_provider: None,
|
||||
profiling_agent: None,
|
||||
memory_profiling_agent: None,
|
||||
tracing_guard: Some(guard),
|
||||
stdout_guard: None,
|
||||
cleanup_handle: None,
|
||||
@@ -389,7 +388,6 @@ fn init_file_logging_internal(
|
||||
meter_provider: None,
|
||||
logger_provider: None,
|
||||
profiling_agent: None,
|
||||
memory_profiling_agent: None,
|
||||
tracing_guard: Some(guard),
|
||||
stdout_guard,
|
||||
cleanup_handle: Some(cleanup_handle),
|
||||
|
||||
@@ -40,7 +40,7 @@ use crate::cleaner::types::FileMatchMode;
|
||||
use crate::config::OtelConfig;
|
||||
use crate::global::set_observability_metric_enabled;
|
||||
use crate::telemetry::filter::build_env_filter;
|
||||
use crate::telemetry::guard::{MemoryProfilingAgent, OtelGuard, ProfilingAgent};
|
||||
use crate::telemetry::guard::{OtelGuard, ProfilingAgent};
|
||||
use crate::telemetry::local::{build_json_log_layer, spawn_cleanup_task};
|
||||
use crate::telemetry::recorder::Recorder;
|
||||
use crate::telemetry::resource::build_resource;
|
||||
@@ -173,7 +173,6 @@ pub(super) fn init_observability_http(
|
||||
let meter_provider = build_meter_provider(&metric_ep, config, res.clone(), &service_name, use_stdout)?;
|
||||
|
||||
let profiling_agent = init_profiler(config);
|
||||
let memory_profiling_agent = init_memory_profiler(config);
|
||||
|
||||
// ── Logger Logic ──────────────────────────────────────────────────────────
|
||||
// Logging is the only signal that may intentionally route to either OTLP
|
||||
@@ -317,7 +316,6 @@ pub(super) fn init_observability_http(
|
||||
meter_provider,
|
||||
logger_provider,
|
||||
profiling_agent,
|
||||
memory_profiling_agent,
|
||||
tracing_guard,
|
||||
stdout_guard,
|
||||
cleanup_handle,
|
||||
@@ -563,65 +561,6 @@ fn init_profiler(_config: &OtelConfig) -> Option<ProfilingAgent> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Initialise a Pyroscope agent for continuous **memory** profiling via jemalloc.
|
||||
///
|
||||
/// This is only available on `linux + gnu + x86_64` where tikv-jemallocator
|
||||
/// is the global allocator and `jemalloc_pprof::PROF_CTL` is accessible.
|
||||
///
|
||||
/// Returns `None` when profiling export is disabled, the endpoint is missing,
|
||||
/// jemalloc profiling is not activated, or the agent fails to build/start.
|
||||
#[cfg(all(feature = "pyroscope", target_os = "linux", target_env = "gnu", target_arch = "x86_64"))]
|
||||
fn init_memory_profiler(config: &OtelConfig) -> Option<MemoryProfilingAgent> {
|
||||
use pyroscope::backend::jemalloc_backend;
|
||||
use pyroscope::pyroscope::PyroscopeAgentBuilder;
|
||||
use rustfs_config::VERSION;
|
||||
|
||||
if !config
|
||||
.profiling_export_enabled
|
||||
.unwrap_or(rustfs_config::DEFAULT_OBS_PROFILING_EXPORT_ENABLED)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
let endpoint = config.profiling_endpoint.as_ref()?.as_str();
|
||||
if endpoint.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Verify jemalloc profiling is available and activated
|
||||
{
|
||||
let prof_ctl = jemalloc_pprof::PROF_CTL.as_ref()?;
|
||||
let ctl = prof_ctl.try_lock().ok()?;
|
||||
if !ctl.activated() {
|
||||
eprintln!("Memory profiling skipped: jemalloc profiling is not activated");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let backend = jemalloc_backend();
|
||||
let service_name = config.service_name.as_deref().unwrap_or(APP_NAME);
|
||||
let version = config.service_version.as_deref().unwrap_or(VERSION);
|
||||
let sample_rate = 100;
|
||||
|
||||
let agent = PyroscopeAgentBuilder::new(endpoint, service_name, sample_rate, "pyroscope-rs", "1.0.1", backend)
|
||||
.tags(vec![("version", version), ("profile_type", "memory")])
|
||||
.build()
|
||||
.ok()?;
|
||||
|
||||
match agent.start() {
|
||||
Ok(agent) => Some(agent),
|
||||
Err(err) => {
|
||||
eprintln!("Memory profiling agent start error: {err:?}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(all(feature = "pyroscope", target_os = "linux", target_env = "gnu", target_arch = "x86_64")))]
|
||||
fn init_memory_profiler(_config: &OtelConfig) -> Option<MemoryProfilingAgent> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Create a stdout periodic metrics reader for the given interval.
|
||||
///
|
||||
/// This helper is primarily used for local development and diagnostics when
|
||||
|
||||
Reference in New Issue
Block a user