-
Notifications
You must be signed in to change notification settings - Fork 164
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bridge: Use jemalloc as the global allocator, except for windows (#1051)
This PR changes the global allocator for svix-bridge to jemalloc. Said allocator is only enabled on non-Windows targets. This also includes some runtime memory metrics exposed via opentelemetry.
- Loading branch information
Showing
5 changed files
with
222 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
//! Allocator stats are only available when we're using jemalloc, and jemalloc doesn't work on windows. | ||
//! | ||
//! 2 impls for the helper functions are therefore provided. One set that does nothing (for windows) | ||
//! and another that works in the non-windows world. | ||
//! | ||
//! Care should be taken to keep the signatures aligned between these two so the callsites can be | ||
//! used consistently regardless of whether jemalloc is in use or not. | ||
|
||
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))] | ||
pub use supported::*; | ||
#[cfg(any(target_env = "msvc", not(feature = "jemalloc")))] | ||
pub use unsupported::*; | ||
|
||
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))] | ||
mod supported { | ||
use std::sync::Arc; | ||
use tikv_jemalloc_ctl::{epoch, stats}; | ||
|
||
pub struct AllocatorStatMibs { | ||
epoch: tikv_jemalloc_ctl::epoch_mib, | ||
allocated: stats::allocated_mib, | ||
resident: stats::resident_mib, | ||
} | ||
|
||
pub fn get_allocator_stats( | ||
bust_cache: bool, | ||
mibs: Arc<AllocatorStatMibs>, | ||
) -> anyhow::Result<Option<(usize, usize)>> { | ||
if bust_cache { | ||
// Stats are cached internally and advancing the epoch is a way to invalidate those caches. | ||
mibs.epoch.advance()?; | ||
} | ||
let allocated = mibs.allocated.read()?; | ||
let resident = mibs.resident.read()?; | ||
Ok(Some((allocated, resident))) | ||
} | ||
|
||
pub fn get_allocator_stat_mibs() -> anyhow::Result<Arc<AllocatorStatMibs>> { | ||
let e = epoch::mib()?; | ||
let allocated = stats::allocated::mib()?; | ||
let resident = stats::resident::mib()?; | ||
|
||
Ok(Arc::new(AllocatorStatMibs { | ||
epoch: e, | ||
allocated, | ||
resident, | ||
})) | ||
} | ||
} | ||
|
||
#[cfg(any(target_env = "msvc", not(feature = "jemalloc")))] | ||
mod unsupported { | ||
use anyhow::anyhow; | ||
use std::sync::Arc; | ||
pub struct AllocatorStatMibs; | ||
|
||
pub fn get_allocator_stats( | ||
_bust_cache: bool, | ||
_mibs: Arc<AllocatorStatMibs>, | ||
) -> anyhow::Result<Option<(usize, usize)>> { | ||
Ok(None) | ||
} | ||
|
||
pub fn get_allocator_stat_mibs() -> anyhow::Result<Arc<AllocatorStatMibs>> { | ||
Err(anyhow!("metric collection is not supported")) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
use opentelemetry::metrics::{Meter, ObservableGauge}; | ||
use opentelemetry::Context; | ||
|
||
fn init_metric<T, E: std::fmt::Display>(result: Result<T, E>) -> Option<T> { | ||
match result { | ||
Ok(t) => Some(t), | ||
Err(e) => { | ||
tracing::error!("Failed to initialize metric: {}", e); | ||
None | ||
} | ||
} | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct CommonMetrics { | ||
mem_allocated_recorder: Option<ObservableGauge<u64>>, | ||
mem_resident_recorder: Option<ObservableGauge<u64>>, | ||
} | ||
|
||
impl CommonMetrics { | ||
pub fn new(meter: &Meter) -> Self { | ||
let mem_resident_recorder = | ||
init_metric(meter.u64_observable_gauge("svix.mem_resident").try_init()); | ||
let mem_allocated_recorder = | ||
init_metric(meter.u64_observable_gauge("svix.mem_allocated").try_init()); | ||
|
||
Self { | ||
mem_allocated_recorder, | ||
mem_resident_recorder, | ||
} | ||
} | ||
|
||
pub fn record_mem_allocated(&self, value: u64) { | ||
if let Some(ref recorder) = self.mem_allocated_recorder { | ||
recorder.observe(&Context::current(), value, &[]); | ||
} | ||
} | ||
|
||
pub fn record_mem_resident(&self, value: u64) { | ||
if let Some(ref recorder) = self.mem_resident_recorder { | ||
recorder.observe(&Context::current(), value, &[]); | ||
} | ||
} | ||
} |