let the benchmark breathe a little better

This commit is contained in:
Toby Lawrence 2020-10-27 23:43:39 -04:00
parent 4f1b57cccc
commit 540fcfd25b
2 changed files with 96 additions and 45 deletions

View File

@ -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");

View File

@ -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(