let the benchmark breathe a little better
This commit is contained in:
parent
4f1b57cccc
commit
540fcfd25b
|
@ -4,6 +4,7 @@ use hdrhistogram::Histogram;
|
|||
use log::{error, info};
|
||||
use metrics::{gauge, histogram, increment};
|
||||
use metrics_util::DebuggingRecorder;
|
||||
use quanta::{Clock, Instant as QuantaInstant};
|
||||
use std::{
|
||||
env,
|
||||
ops::Sub,
|
||||
|
@ -18,7 +19,7 @@ use std::{
|
|||
const LOOP_SAMPLE: u64 = 1000;
|
||||
|
||||
struct Generator {
|
||||
t0: Option<Instant>,
|
||||
t0: Option<QuantaInstant>,
|
||||
gauge: i64,
|
||||
hist: Histogram<u64>,
|
||||
done: Arc<AtomicBool>,
|
||||
|
@ -37,6 +38,7 @@ impl Generator {
|
|||
}
|
||||
|
||||
fn run(&mut self) {
|
||||
let mut clock = Clock::new();
|
||||
let mut counter = 0;
|
||||
loop {
|
||||
counter += 1;
|
||||
|
@ -47,11 +49,11 @@ impl Generator {
|
|||
|
||||
self.gauge += 1;
|
||||
|
||||
let t1 = Instant::now();
|
||||
let t1 = clock.now();
|
||||
|
||||
if let Some(t0) = self.t0 {
|
||||
let start = if counter % 1000 == 0 {
|
||||
Some(Instant::now())
|
||||
let start = if counter % LOOP_SAMPLE == 0 {
|
||||
Some(clock.now())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -61,7 +63,7 @@ impl Generator {
|
|||
histogram!("ok", t1.sub(t0));
|
||||
|
||||
if let Some(val) = start {
|
||||
let delta = Instant::now() - val;
|
||||
let delta = clock.now() - val;
|
||||
self.hist.saturating_record(delta.as_nanos() as u64);
|
||||
|
||||
// We also increment our global counter for the sample rate here.
|
||||
|
@ -146,7 +148,7 @@ fn main() {
|
|||
info!("duration: {}s", seconds);
|
||||
info!("producers: {}", producers);
|
||||
|
||||
let recorder = DebuggingRecorder::new();
|
||||
let recorder = DebuggingRecorder::with_ordering(false);
|
||||
let snapshotter = recorder.snapshotter();
|
||||
recorder.install().expect("failed to install recorder");
|
||||
|
||||
|
|
|
@ -7,6 +7,16 @@ use crate::{handle::Handle, registry::Registry};
|
|||
use indexmap::IndexMap;
|
||||
use metrics::{Key, Recorder, Unit};
|
||||
|
||||
type UnitMap = Arc<Mutex<HashMap<DifferentiatedKey, Unit>>>;
|
||||
type DescriptionMap = Arc<Mutex<HashMap<DifferentiatedKey, &'static str>>>;
|
||||
type Snapshot = Vec<(
|
||||
MetricKind,
|
||||
Key,
|
||||
Option<Unit>,
|
||||
Option<&'static str>,
|
||||
DebugValue,
|
||||
)>;
|
||||
|
||||
/// Metric kinds.
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy, Ord, PartialOrd)]
|
||||
pub enum MetricKind {
|
||||
|
@ -63,51 +73,73 @@ impl Hash for DebugValue {
|
|||
/// Captures point-in-time snapshots of `DebuggingRecorder`.
|
||||
pub struct Snapshotter {
|
||||
registry: Arc<Registry<DifferentiatedKey, Handle>>,
|
||||
metrics: Arc<Mutex<IndexMap<DifferentiatedKey, ()>>>,
|
||||
units: Arc<Mutex<HashMap<DifferentiatedKey, Unit>>>,
|
||||
descriptions: Arc<Mutex<HashMap<DifferentiatedKey, &'static str>>>,
|
||||
metrics: Option<Arc<Mutex<IndexMap<DifferentiatedKey, ()>>>>,
|
||||
units: UnitMap,
|
||||
descriptions: DescriptionMap,
|
||||
}
|
||||
|
||||
impl Snapshotter {
|
||||
/// Takes a snapshot of the recorder.
|
||||
pub fn snapshot(
|
||||
&self,
|
||||
) -> Vec<(
|
||||
MetricKind,
|
||||
Key,
|
||||
Option<Unit>,
|
||||
Option<&'static str>,
|
||||
DebugValue,
|
||||
)> {
|
||||
pub fn snapshot(&self) -> Snapshot {
|
||||
let mut snapshot = Vec::new();
|
||||
let handles = self.registry.get_handles();
|
||||
let metrics = {
|
||||
let metrics = self.metrics.lock().expect("metrics lock poisoned");
|
||||
metrics.clone()
|
||||
|
||||
let collect_metric = |dkey: DifferentiatedKey,
|
||||
handle: &Handle,
|
||||
units: &UnitMap,
|
||||
descs: &DescriptionMap,
|
||||
snapshot: &mut Snapshot| {
|
||||
let unit = units
|
||||
.lock()
|
||||
.expect("units lock poisoned")
|
||||
.get(&dkey)
|
||||
.cloned();
|
||||
let desc = descs
|
||||
.lock()
|
||||
.expect("descriptions lock poisoned")
|
||||
.get(&dkey)
|
||||
.cloned();
|
||||
let (kind, key) = dkey.into_parts();
|
||||
let value = match kind {
|
||||
MetricKind::Counter => DebugValue::Counter(handle.read_counter()),
|
||||
MetricKind::Gauge => DebugValue::Gauge(handle.read_gauge()),
|
||||
MetricKind::Histogram => DebugValue::Histogram(handle.read_histogram()),
|
||||
};
|
||||
snapshot.push((kind, key, unit, desc, value));
|
||||
};
|
||||
for (dkey, _) in metrics.into_iter() {
|
||||
if let Some(handle) = handles.get(&dkey) {
|
||||
let unit = self
|
||||
.units
|
||||
.lock()
|
||||
.expect("units lock poisoned")
|
||||
.get(&dkey)
|
||||
.cloned();
|
||||
let description = self
|
||||
.descriptions
|
||||
.lock()
|
||||
.expect("descriptions lock poisoned")
|
||||
.get(&dkey)
|
||||
.cloned();
|
||||
let (kind, key) = dkey.into_parts();
|
||||
let value = match kind {
|
||||
MetricKind::Counter => DebugValue::Counter(handle.read_counter()),
|
||||
MetricKind::Gauge => DebugValue::Gauge(handle.read_gauge()),
|
||||
MetricKind::Histogram => DebugValue::Histogram(handle.read_histogram()),
|
||||
|
||||
match &self.metrics {
|
||||
Some(inner) => {
|
||||
let metrics = {
|
||||
let metrics = inner.lock().expect("metrics lock poisoned");
|
||||
metrics.clone()
|
||||
};
|
||||
snapshot.push((kind, key, unit, description, value));
|
||||
|
||||
for (dkey, _) in metrics.into_iter() {
|
||||
if let Some(handle) = handles.get(&dkey) {
|
||||
collect_metric(
|
||||
dkey,
|
||||
handle,
|
||||
&self.units,
|
||||
&self.descriptions,
|
||||
&mut snapshot,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
for (dkey, handle) in handles.into_iter() {
|
||||
collect_metric(
|
||||
dkey,
|
||||
&handle,
|
||||
&self.units,
|
||||
&self.descriptions,
|
||||
&mut snapshot,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snapshot
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +150,7 @@ impl Snapshotter {
|
|||
/// to the raw values.
|
||||
pub struct DebuggingRecorder {
|
||||
registry: Arc<Registry<DifferentiatedKey, Handle>>,
|
||||
metrics: Arc<Mutex<IndexMap<DifferentiatedKey, ()>>>,
|
||||
metrics: Option<Arc<Mutex<IndexMap<DifferentiatedKey, ()>>>>,
|
||||
units: Arc<Mutex<HashMap<DifferentiatedKey, Unit>>>,
|
||||
descriptions: Arc<Mutex<HashMap<DifferentiatedKey, &'static str>>>,
|
||||
}
|
||||
|
@ -126,9 +158,24 @@ pub struct DebuggingRecorder {
|
|||
impl DebuggingRecorder {
|
||||
/// Creates a new `DebuggingRecorder`.
|
||||
pub fn new() -> DebuggingRecorder {
|
||||
Self::with_ordering(true)
|
||||
}
|
||||
|
||||
/// Creates a new `DebuggingRecorder` with ordering enabled or disabled.
|
||||
///
|
||||
/// When ordering is enabled, any snapshotter derived from this recorder will iterate the
|
||||
/// collected metrics in order of when the metric was first observed. If ordering is disabled,
|
||||
/// then the iteration order is undefined.
|
||||
pub fn with_ordering(ordered: bool) -> Self {
|
||||
let metrics = if ordered {
|
||||
Some(Arc::new(Mutex::new(IndexMap::new())))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
DebuggingRecorder {
|
||||
registry: Arc::new(Registry::new()),
|
||||
metrics: Arc::new(Mutex::new(IndexMap::new())),
|
||||
metrics,
|
||||
units: Arc::new(Mutex::new(HashMap::new())),
|
||||
descriptions: Arc::new(Mutex::new(HashMap::new())),
|
||||
}
|
||||
|
@ -145,8 +192,10 @@ impl DebuggingRecorder {
|
|||
}
|
||||
|
||||
fn register_metric(&self, rkey: DifferentiatedKey) {
|
||||
let mut metrics = self.metrics.lock().expect("metrics lock poisoned");
|
||||
let _ = metrics.insert(rkey.clone(), ());
|
||||
if let Some(metrics) = &self.metrics {
|
||||
let mut metrics = metrics.lock().expect("metrics lock poisoned");
|
||||
let _ = metrics.entry(rkey.clone()).or_insert(());
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_unit_description(
|
||||
|
|
Loading…
Reference in New Issue