From 281b6e2740642447294c08973b7d3824ded2df80 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Mon, 13 May 2024 09:17:23 -0700 Subject: [PATCH] deps: update metrics to a more recent version This isn't the latest version of metrics; it's just a more recent version that allows us to remove a duplicate ahash dependency from the build graph. --- Cargo.lock | 36 ++- codec/Cargo.toml | 2 +- lfucache/Cargo.toml | 2 +- .../color-funcs/src/image_colors.rs | 2 +- mux/Cargo.toml | 2 +- term/src/terminalstate/mod.rs | 2 +- wezterm-client/Cargo.toml | 2 +- wezterm-client/src/pane/renderable.rs | 6 +- wezterm-font/Cargo.toml | 2 +- wezterm-gui/Cargo.toml | 2 +- wezterm-gui/src/stats.rs | 245 +++++++++++------- window/Cargo.toml | 2 +- 12 files changed, 186 insertions(+), 119 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 022aea768..1161ee447 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,17 +23,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - [[package]] name = "ahash" version = "0.8.11" @@ -2348,7 +2337,7 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.11", + "ahash", "allocator-api2", ] @@ -2898,7 +2887,7 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" name = "lfucache" version = "0.1.0" dependencies = [ - "ahash 0.8.11", + "ahash", "config", "fnv", "intrusive-collections", @@ -3295,25 +3284,24 @@ dependencies = [ [[package]] name = "metrics" -version = "0.17.1" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55586aa936c35f34ba8aa5d97356d554311206e1ce1f9e68fe7b07288e5ad827" +checksum = "fde3af1a009ed76a778cb84fdef9e7dbbdf5775ae3e4cc1f434a6a307f6f76c5" dependencies = [ - "ahash 0.7.8", + "ahash", "metrics-macros", + "portable-atomic", ] [[package]] name = "metrics-macros" -version = "0.4.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0daa0ab3a0ae956d0e2c1f42511422850e577d36a255357d1a7d08d45ee3a2f1" +checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" dependencies = [ - "lazy_static", "proc-macro2", "quote", - "regex", - "syn 1.0.109", + "syn 2.0.63", ] [[package]] @@ -4196,6 +4184,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + [[package]] name = "portable-pty" version = "0.8.1" diff --git a/codec/Cargo.toml b/codec/Cargo.toml index 52b250176..9347bb5c3 100644 --- a/codec/Cargo.toml +++ b/codec/Cargo.toml @@ -12,7 +12,7 @@ anyhow = "1.0" config = { path = "../config" } leb128 = "0.2" log = "0.4" -metrics = { version="0.17", features=["std"]} +metrics = "0.21" mux = { path = "../mux" } portable-pty = { path = "../pty", features = ["serde_support"]} rangeset = { path = "../rangeset" } diff --git a/lfucache/Cargo.toml b/lfucache/Cargo.toml index ce861ec41..6aebc2350 100644 --- a/lfucache/Cargo.toml +++ b/lfucache/Cargo.toml @@ -11,7 +11,7 @@ ahash = "0.8" config = { path = "../config" } fnv = "1.0" intrusive-collections = "0.9" -metrics = { version="0.17", features=["std"]} +metrics = "0.21" [dev-dependencies] k9 = "0.12" diff --git a/lua-api-crates/color-funcs/src/image_colors.rs b/lua-api-crates/color-funcs/src/image_colors.rs index d56967096..8dc0b79ee 100644 --- a/lua-api-crates/color-funcs/src/image_colors.rs +++ b/lua-api-crates/color-funcs/src/image_colors.rs @@ -18,8 +18,8 @@ use deltae::LabValue; use image::Pixel; use lru::LruCache; use luahelper::impl_lua_conversion_dynamic; -use std::num::NonZeroUsize; use std::collections::HashMap; +use std::num::NonZeroUsize; use std::sync::Mutex; use std::time::SystemTime; use wezterm_dynamic::{FromDynamic, ToDynamic}; diff --git a/mux/Cargo.toml b/mux/Cargo.toml index d7cd3c2e5..85d808226 100644 --- a/mux/Cargo.toml +++ b/mux/Cargo.toml @@ -25,7 +25,7 @@ lazy_static = "1.4" libc = "0.2" log = "0.4" luahelper = { path = "../luahelper" } -metrics = { version="0.17", features=["std"]} +metrics = "0.21" mlua = "0.9" names = { version = "0.12", default-features = false } nix = {version="0.25", features=["term"]} diff --git a/term/src/terminalstate/mod.rs b/term/src/terminalstate/mod.rs index 6a7f83739..02d1690af 100644 --- a/term/src/terminalstate/mod.rs +++ b/term/src/terminalstate/mod.rs @@ -5,10 +5,10 @@ use super::*; use crate::color::{ColorPalette, RgbColor}; use crate::config::{BidiMode, NewlineCanon}; use log::debug; -use std::num::NonZeroUsize; use num_traits::ToPrimitive; use std::collections::HashMap; use std::io::{BufWriter, Write}; +use std::num::NonZeroUsize; use std::sync::mpsc::{channel, Sender}; use std::sync::Arc; use terminfo::{Database, Value}; diff --git a/wezterm-client/Cargo.toml b/wezterm-client/Cargo.toml index a868d1fa9..9ed0f26f2 100644 --- a/wezterm-client/Cargo.toml +++ b/wezterm-client/Cargo.toml @@ -19,7 +19,7 @@ lazy_static = "1.4" log = "0.4" libc = "0.2" lru = "0.12" -metrics = { version="0.17", features=["std"]} +metrics = "0.21" mux = { path = "../mux" } openssl = "0.10.57" parking_lot = "0.12" diff --git a/wezterm-client/src/pane/renderable.rs b/wezterm-client/src/pane/renderable.rs index 0bb947129..68fa518f8 100644 --- a/wezterm-client/src/pane/renderable.rs +++ b/wezterm-client/src/pane/renderable.rs @@ -1,5 +1,4 @@ use crate::domain::ClientInner; -use std::num::NonZeroUsize; use crate::pane::clientpane::ClientPane; use anyhow::anyhow; use codec::*; @@ -13,6 +12,7 @@ use rangeset::*; use ratelim::RateLimiter; use std::cell::RefCell; use std::collections::HashMap; +use std::num::NonZeroUsize; use std::ops::Range; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; @@ -105,7 +105,9 @@ impl RenderableInner { poll_interval: BASE_POLL_INTERVAL, cursor_position: StableCursorPosition::default(), dimensions, - lines: LruCache::new(NonZeroUsize::new(configuration().scrollback_lines.max(128)).unwrap()), + lines: LruCache::new( + NonZeroUsize::new(configuration().scrollback_lines.max(128)).unwrap(), + ), title: title.to_string(), working_dir: None, fetch_limiter, diff --git a/wezterm-font/Cargo.toml b/wezterm-font/Cargo.toml index 2a18e0a08..0cd073ece 100644 --- a/wezterm-font/Cargo.toml +++ b/wezterm-font/Cargo.toml @@ -28,7 +28,7 @@ lazy_static = "1.4" lfucache = { path = "../lfucache" } log = "0.4" memmap2 = "0.2" -metrics = { version="0.17", features=["std"]} +metrics = "0.21" ordered-float = "4.1" rangeset = { path = "../rangeset" } termwiz = { path = "../termwiz" } diff --git a/wezterm-gui/Cargo.toml b/wezterm-gui/Cargo.toml index e0dd3e0ce..6c6b91771 100644 --- a/wezterm-gui/Cargo.toml +++ b/wezterm-gui/Cargo.toml @@ -62,7 +62,7 @@ libc = "0.2" lfucache = { path = "../lfucache" } log = "0.4" luahelper = { path = "../luahelper" } -metrics = { version="0.17", features=["std"]} +metrics = "0.21" mlua = {version="0.9", features=["send"]} mux = { path = "../mux" } mux-lua = { path = "../lua-api-crates/mux" } diff --git a/wezterm-gui/src/stats.rs b/wezterm-gui/src/stats.rs index b046986fc..ee48b9cd1 100644 --- a/wezterm-gui/src/stats.rs +++ b/wezterm-gui/src/stats.rs @@ -2,10 +2,11 @@ use config::configuration; use config::lua::get_or_create_sub_module; use config::lua::mlua::Lua; use hdrhistogram::Histogram; -use metrics::{GaugeValue, Key, Recorder, Unit}; +use metrics::{Counter, Gauge, Key, KeyName, Recorder, SharedString, Unit}; +use parking_lot::Mutex; use std::collections::HashMap; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Mutex}; +use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use std::sync::Arc; use std::time::{Duration, Instant}; use tabout::{tabulate_output, Alignment, Column}; @@ -14,21 +15,40 @@ lazy_static::lazy_static! { static ref INNER: Arc> = make_inner(); } -struct Throughput { +struct ThroughputInner { hist: Histogram, last: Option, count: u64, } +struct Throughput { + inner: Mutex, +} + impl Throughput { fn new() -> Self { Self { - hist: Histogram::new(2).expect("failed to create histogram"), - last: None, - count: 0, + inner: Mutex::new(ThroughputInner { + hist: Histogram::new(2).expect("failed to create histogram"), + last: None, + count: 0, + }), } } + fn current(&self) -> u64 { + self.inner.lock().current() + } + fn percentiles(&self) -> (u64, u64, u64) { + let inner = self.inner.lock(); + let p50 = inner.hist.value_at_percentile(50.); + let p75 = inner.hist.value_at_percentile(75.); + let p95 = inner.hist.value_at_percentile(95.); + (p50, p75, p95) + } +} + +impl ThroughputInner { fn add(&mut self, value: u64) { if let Some(ref last) = self.last { let elapsed = last.elapsed(); @@ -57,14 +77,69 @@ impl Throughput { } } +impl metrics::HistogramFn for Throughput { + fn record(&self, value: f64) { + self.inner.lock().add(value as u64); + } +} + +struct ScaledHistogram { + hist: Mutex>, + scale: f64, +} + +impl ScaledHistogram { + fn new(scale: f64) -> Arc { + Arc::new(Self { + hist: Mutex::new(Histogram::new(2).expect("failed to create new Histogram")), + scale, + }) + } + fn percentiles(&self) -> (u64, u64, u64) { + let hist = self.hist.lock(); + let p50 = hist.value_at_percentile(50.); + let p75 = hist.value_at_percentile(75.); + let p95 = hist.value_at_percentile(95.); + (p50, p75, p95) + } + + fn latency_percentiles(&self) -> (Duration, Duration, Duration) { + let hist = self.hist.lock(); + let p50 = pctile_latency(&*hist, 50.); + let p75 = pctile_latency(&*hist, 75.); + let p95 = pctile_latency(&*hist, 95.); + (p50, p75, p95) + } +} + +impl metrics::HistogramFn for ScaledHistogram { + fn record(&self, value: f64) { + self.hist.lock().record((value * self.scale) as u64).ok(); + } +} + fn pctile_latency(histogram: &Histogram, p: f64) -> Duration { Duration::from_nanos(histogram.value_at_percentile(p)) } +struct MyCounter { + value: AtomicUsize, +} + +impl metrics::CounterFn for MyCounter { + fn increment(&self, value: u64) { + self.value.fetch_add(value as usize, Ordering::Relaxed); + } + + fn absolute(&self, value: u64) { + self.value.store(value as usize, Ordering::Relaxed); + } +} + struct Inner { - histograms: HashMap>, - throughput: HashMap, - counters: HashMap, + histograms: HashMap>, + throughput: HashMap>, + counters: HashMap>, } impl Inner { @@ -136,12 +211,10 @@ impl Inner { if last_print.elapsed() >= Duration::from_secs(seconds) { let mut data = vec![]; - let mut inner = inner.lock().unwrap(); + let mut inner = inner.lock(); for (key, tput) in &mut inner.throughput { let current = tput.current(); - let p50 = tput.hist.value_at_percentile(50.); - let p75 = tput.hist.value_at_percentile(75.); - let p95 = tput.hist.value_at_percentile(95.); + let (p50, p75, p95) = tput.percentiles(); data.push(vec![ key.to_string(), format!("{:.2?}", current), @@ -157,9 +230,7 @@ impl Inner { data.clear(); for (key, histogram) in &inner.histograms { if key.name().ends_with(".size") { - let p50 = histogram.value_at_percentile(50.); - let p75 = histogram.value_at_percentile(75.); - let p95 = histogram.value_at_percentile(95.); + let (p50, p75, p95) = histogram.percentiles(); data.push(vec![ key.to_string(), format!("{:.2?}", p50), @@ -167,9 +238,7 @@ impl Inner { format!("{:.2?}", p95), ]); } else { - let p50 = pctile_latency(histogram, 50.); - let p75 = pctile_latency(histogram, 75.); - let p95 = pctile_latency(histogram, 95.); + let (p50, p75, p95) = histogram.latency_percentiles(); data.push(vec![ key.to_string(), format!("{:.2?}", p50), @@ -184,7 +253,10 @@ impl Inner { data.clear(); for (key, count) in &inner.counters { - data.push(vec![key.to_string(), count.to_string()]); + data.push(vec![ + key.to_string(), + count.value.load(Ordering::Relaxed).to_string(), + ]); } data.sort_by(|a, b| a[0].cmp(&b[0])); eprintln!(); @@ -226,54 +298,59 @@ impl Stats { } impl Recorder for Stats { - fn register_counter( - &self, - _key: &Key, - _unit: Option, - _description: Option<&'static str>, - ) { + fn describe_counter(&self, _key: KeyName, _unit: Option, _description: SharedString) {} + + fn describe_gauge(&self, _key: KeyName, _unit: Option, _description: SharedString) {} + + fn describe_histogram(&self, _key: KeyName, _unit: Option, _description: SharedString) {} + + fn register_counter(&self, key: &Key) -> Counter { + let mut inner = self.inner.lock(); + match inner.counters.get(key) { + Some(existing) => Counter::from_arc(existing.clone()), + None => { + let counter = Arc::new(MyCounter { + value: AtomicUsize::new(0), + }); + inner.counters.insert(key.clone(), counter.clone()); + metrics::Counter::from_arc(counter) + } + } } - fn register_gauge(&self, _key: &Key, _unit: Option, _description: Option<&'static str>) {} - - fn register_histogram( - &self, - _key: &Key, - _unit: Option, - _description: Option<&'static str>, - ) { + fn register_gauge(&self, _key: &Key) -> Gauge { + Gauge::noop() } - fn increment_counter(&self, key: &Key, value: u64) { - let mut inner = self.inner.lock().unwrap(); - let counter = inner.counters.entry(key.clone()).or_insert_with(|| 0); - *counter = *counter + value; - } - - fn update_gauge(&self, key: &Key, value: GaugeValue) { - log::trace!("gauge '{}' -> {:?}", key, value); - } - - fn record_histogram(&self, key: &Key, value: f64) { - let mut inner = self.inner.lock().unwrap(); + fn register_histogram(&self, key: &Key) -> metrics::Histogram { + let mut inner = self.inner.lock(); if key.name().ends_with(".rate") { - let tput = inner - .throughput - .entry(key.clone()) - .or_insert_with(|| Throughput::new()); - tput.add(value as u64); + match inner.throughput.get(key) { + Some(existing) => metrics::Histogram::from_arc(existing.clone()), + None => { + let tput = Arc::new(Throughput::new()); + inner.throughput.insert(key.clone(), tput.clone()); + + metrics::Histogram::from_arc(tput) + } + } } else { - let value = if key.name().ends_with(".size") { - value - } else { - // Assume seconds; convert to nanoseconds - value * 1_000_000_000.0 - }; - let histogram = inner - .histograms - .entry(key.clone()) - .or_insert_with(|| Histogram::new(2).expect("failed to crate new Histogram")); - histogram.record(value as u64).ok(); + match inner.histograms.get(key) { + Some(existing) => metrics::Histogram::from_arc(existing.clone()), + None => { + let scale = if key.name().ends_with(".size") { + 1.0 + } else { + // Assume seconds; convert to nanoseconds + 1_000_000_000.0 + }; + + let histogram = ScaledHistogram::new(scale); + inner.histograms.insert(key.clone(), histogram.clone()); + + metrics::Histogram::from_arc(histogram) + } + } } } } @@ -283,11 +360,11 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> { metrics_mod.set( "get_counters", lua.create_function(|_, _: ()| { - let inner = INNER.lock().unwrap(); - let counters: HashMap = inner + let inner = INNER.lock(); + let counters: HashMap = inner .counters .iter() - .map(|(k, &v)| (k.name().to_string(), v)) + .map(|(k, v)| (k.name().to_string(), v.value.load(Ordering::Relaxed))) .collect(); Ok(counters) })?, @@ -295,16 +372,17 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> { metrics_mod.set( "get_throughput", lua.create_function(|_, _: ()| { - let mut inner = INNER.lock().unwrap(); + let mut inner = INNER.lock(); let counters: HashMap> = inner .throughput .iter_mut() .map(|(k, tput)| { let mut res = HashMap::new(); res.insert("current".to_string(), tput.current()); - res.insert("p50".to_string(), tput.hist.value_at_percentile(50.)); - res.insert("p75".to_string(), tput.hist.value_at_percentile(75.)); - res.insert("p95".to_string(), tput.hist.value_at_percentile(95.)); + let (p50, p75, p95) = tput.percentiles(); + res.insert("p50".to_string(), p50); + res.insert("p75".to_string(), p75); + res.insert("p95".to_string(), p95); (k.name().to_string(), res) }) .collect(); @@ -314,16 +392,17 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> { metrics_mod.set( "get_sizes", lua.create_function(|_, _: ()| { - let mut inner = INNER.lock().unwrap(); + let mut inner = INNER.lock(); let counters: HashMap> = inner .histograms .iter_mut() .filter_map(|(key, hist)| { if key.name().ends_with(".size") { let mut res = HashMap::new(); - res.insert("p50".to_string(), hist.value_at_percentile(50.)); - res.insert("p75".to_string(), hist.value_at_percentile(75.)); - res.insert("p95".to_string(), hist.value_at_percentile(95.)); + let (p50, p75, p95) = hist.percentiles(); + res.insert("p50".to_string(), p50); + res.insert("p75".to_string(), p75); + res.insert("p95".to_string(), p95); Some((key.name().to_string(), res)) } else { None @@ -336,25 +415,17 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> { metrics_mod.set( "get_latency", lua.create_function(|_, _: ()| { - let mut inner = INNER.lock().unwrap(); + let mut inner = INNER.lock(); let counters: HashMap> = inner .histograms .iter_mut() .filter_map(|(key, hist)| { if !key.name().ends_with(".size") { let mut res = HashMap::new(); - res.insert( - "p50".to_string(), - format!("{:?}", pctile_latency(hist, 50.)), - ); - res.insert( - "p75".to_string(), - format!("{:?}", pctile_latency(hist, 75.)), - ); - res.insert( - "p95".to_string(), - format!("{:?}", pctile_latency(hist, 95.)), - ); + let (p50, p75, p95) = hist.latency_percentiles(); + res.insert("p50".to_string(), format!("{p50:?}")); + res.insert("p75".to_string(), format!("{p75:?}")); + res.insert("p95".to_string(), format!("{p95:?}")); Some((key.name().to_string(), res)) } else { None diff --git a/window/Cargo.toml b/window/Cargo.toml index 580c6d7aa..1a96033cb 100644 --- a/window/Cargo.toml +++ b/window/Cargo.toml @@ -34,7 +34,7 @@ lazy_static = "1.4" libloading = "0.6" line_drawing = "0.8" log = "0.4" -metrics = { version="0.17", features=["std"]} +metrics = "0.21" promise = { path = "../promise" } raw-window-handle = "0.5" resize = "0.5"