use crate::debug::Diagnostic;
use bytes::Bytes;
use conjure_error::Error;
use http::HeaderValue;
use refreshable::Refreshable;
use std::{
ffi::{c_char, CString},
fs,
};
use tempfile::NamedTempFile;
use witchcraft_log::{info, warn};
use witchcraft_server_config::runtime::RuntimeConfig;
#[no_mangle]
#[allow(non_upper_case_globals)]
#[cfg(target_os = "linux")]
static malloc_conf: &c_char = unsafe { &*c"prof:true,prof_active:false".as_ptr() };
#[no_mangle]
#[allow(non_upper_case_globals)]
#[cfg(target_os = "macos")]
static _rjem_malloc_conf: &c_char = unsafe { &*c"prof:true,prof_active:false".as_ptr() };
pub fn init<R>(runtime: &Refreshable<R, Error>)
where
R: AsRef<RuntimeConfig> + PartialEq + 'static + Sync + Send,
{
runtime
.map(|r| r.as_ref().diagnostics().jemalloc().prof_active())
.subscribe(|active| {
info!("setting prof.active", safe: { value: active });
if let Err(e) = unsafe {
tikv_jemalloc_ctl::raw::write::<bool>(c"prof.active".to_bytes_with_nul(), *active)
} {
warn!("error setting prof.active", error: Error::internal_safe(e));
}
})
.leak();
runtime
.map(|r| r.as_ref().diagnostics().jemalloc().lg_prof_sample())
.subscribe(|lg_prof_sample| {
info!("setting prof.reset", safe: { value: lg_prof_sample });
if let Err(e) = unsafe {
tikv_jemalloc_ctl::raw::write::<usize>(
c"prof.reset".to_bytes_with_nul(),
*lg_prof_sample,
)
} {
warn!("error setting prof.reset", error: Error::internal_safe(e));
}
})
.leak();
}
pub struct HeapProfileDiagnostic;
impl Diagnostic for HeapProfileDiagnostic {
fn type_(&self) -> &str {
"rust.heap.profile.v1"
}
fn content_type(&self) -> HeaderValue {
HeaderValue::from_static("text/plain")
}
fn safe_loggable(&self) -> bool {
true
}
fn result(&self) -> Result<Bytes, Error> {
let file = NamedTempFile::new_in("var/data/tmp").map_err(Error::internal_safe)?;
let path_str = CString::new(file.path().as_os_str().as_encoded_bytes())
.map_err(Error::internal_safe)?;
unsafe {
tikv_jemalloc_ctl::raw::write::<*const c_char>(
c"prof.dump".to_bytes_with_nul(),
path_str.as_ptr(),
)
.map_err(Error::internal_safe)?;
}
let profile = fs::read_to_string(file.path()).map_err(Error::internal_safe)?;
Ok(Bytes::from(profile))
}
}