Skip to content

Commit da745ff

Browse files
authored
metrics: add H2 Histogram option to improve histogram granularity (#6897)
1 parent ce1c74f commit da745ff

File tree

10 files changed

+869
-127
lines changed

10 files changed

+869
-127
lines changed

spellcheck.dic

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
287
1+
292
22
&
33
+
44
<
@@ -12,12 +12,17 @@
1212
0xA
1313
0xD
1414
100ms
15+
100ns
1516
10ms
17+
10μs
1618
~12
19+
120s
20+
12.5%
1721
±1m
1822
±1ms
1923
1ms
2024
1s
25+
25%
2126
250ms
2227
2x
2328
~4
@@ -116,9 +121,11 @@ GID
116121
goroutines
117122
Growable
118123
gzip
124+
H2
119125
hashmaps
120126
HashMaps
121127
hashsets
128+
HdrHistogram
122129
ie
123130
Illumos
124131
impl

tokio/Cargo.toml

+7-7
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ mio = { version = "1.0.1", optional = true, default-features = false }
9696
parking_lot = { version = "0.12.0", optional = true }
9797

9898
[target.'cfg(not(target_family = "wasm"))'.dependencies]
99-
socket2 = { version = "0.5.5", optional = true, features = [ "all" ] }
99+
socket2 = { version = "0.5.5", optional = true, features = ["all"] }
100100

101101
# Currently unstable. The API exposed by these features may be broken at any time.
102102
# Requires `--cfg tokio_unstable` to enable.
@@ -123,8 +123,8 @@ optional = true
123123
[target.'cfg(windows)'.dev-dependencies.windows-sys]
124124
version = "0.52"
125125
features = [
126-
"Win32_Foundation",
127-
"Win32_Security_Authorization",
126+
"Win32_Foundation",
127+
"Win32_Security_Authorization",
128128
]
129129

130130
[dev-dependencies]
@@ -137,6 +137,7 @@ async-stream = "0.3"
137137
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
138138
socket2 = "0.5.5"
139139
tempfile = "3.1.0"
140+
proptest = "1"
140141

141142
[target.'cfg(not(all(target_family = "wasm", target_os = "unknown")))'.dev-dependencies]
142143
rand = "0.8.0"
@@ -165,8 +166,7 @@ features = ["full", "test-util"]
165166
# The following are types that are allowed to be exposed in Tokio's public API.
166167
# The standard library is allowed by default.
167168
allowed_external_types = [
168-
"bytes::buf::buf_impl::Buf",
169-
"bytes::buf::buf_mut::BufMut",
170-
171-
"tokio_macros::*",
169+
"bytes::buf::buf_impl::Buf",
170+
"bytes::buf::buf_mut::BufMut",
171+
"tokio_macros::*",
172172
]

tokio/src/runtime/builder.rs

+85-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::runtime::handle::Handle;
44
use crate::runtime::{blocking, driver, Callback, HistogramBuilder, Runtime, TaskCallback};
55
#[cfg(tokio_unstable)]
6-
use crate::runtime::{LocalOptions, LocalRuntime, TaskMeta};
6+
use crate::runtime::{metrics::HistogramConfiguration, LocalOptions, LocalRuntime, TaskMeta};
77
use crate::util::rand::{RngSeed, RngSeedGenerator};
88

99
use crate::runtime::blocking::BlockingPool;
@@ -1102,6 +1102,11 @@ impl Builder {
11021102
/// `metrics_poll_count_histogram_` builder methods to configure the
11031103
/// histogram details.
11041104
///
1105+
/// By default, a linear histogram with 10 buckets each 100 microseconds wide will be used.
1106+
/// This has an extremely low memory footprint, but may not provide enough granularity. For
1107+
/// better granularity with low memory usage, use [`metrics_poll_count_histogram_configuration()`]
1108+
/// to select [`LogHistogram`] instead.
1109+
///
11051110
/// # Examples
11061111
///
11071112
/// ```
@@ -1121,6 +1126,8 @@ impl Builder {
11211126
///
11221127
/// [`Handle::metrics()`]: crate::runtime::Handle::metrics
11231128
/// [`Instant::now()`]: std::time::Instant::now
1129+
/// [`LogHistogram`]: crate::runtime::LogHistogram
1130+
/// [`metrics_poll_count_histogram_configuration()`]: Builder::metrics_poll_count_histogram_configuration
11241131
pub fn enable_metrics_poll_count_histogram(&mut self) -> &mut Self {
11251132
self.metrics_poll_count_histogram_enable = true;
11261133
self
@@ -1142,14 +1149,83 @@ impl Builder {
11421149
/// ```
11431150
/// use tokio::runtime::{self, HistogramScale};
11441151
///
1152+
/// # #[allow(deprecated)]
11451153
/// let rt = runtime::Builder::new_multi_thread()
11461154
/// .enable_metrics_poll_count_histogram()
11471155
/// .metrics_poll_count_histogram_scale(HistogramScale::Log)
11481156
/// .build()
11491157
/// .unwrap();
11501158
/// ```
1159+
#[deprecated(note = "use metrics_poll_count_histogram_configuration")]
11511160
pub fn metrics_poll_count_histogram_scale(&mut self, histogram_scale: crate::runtime::HistogramScale) -> &mut Self {
1152-
self.metrics_poll_count_histogram.scale = histogram_scale;
1161+
self.metrics_poll_count_histogram.legacy_mut(|b|b.scale = histogram_scale);
1162+
self
1163+
}
1164+
1165+
/// Configure the histogram for tracking poll times
1166+
///
1167+
/// By default, a linear histogram with 10 buckets each 100 microseconds wide will be used.
1168+
/// This has an extremely low memory footprint, but may not provide enough granularity. For
1169+
/// better granularity with low memory usage, use [`LogHistogram`] instead.
1170+
///
1171+
/// # Examples
1172+
/// Configure a [`LogHistogram`] with [default configuration]:
1173+
/// ```
1174+
/// use tokio::runtime;
1175+
/// use tokio::runtime::{HistogramConfiguration, LogHistogram};
1176+
///
1177+
/// let rt = runtime::Builder::new_multi_thread()
1178+
/// .enable_metrics_poll_count_histogram()
1179+
/// .metrics_poll_count_histogram_configuration(
1180+
/// HistogramConfiguration::log(LogHistogram::default())
1181+
/// )
1182+
/// .build()
1183+
/// .unwrap();
1184+
/// ```
1185+
///
1186+
/// Configure a linear histogram with 100 buckets, each 10μs wide
1187+
/// ```
1188+
/// use tokio::runtime;
1189+
/// use std::time::Duration;
1190+
/// use tokio::runtime::HistogramConfiguration;
1191+
///
1192+
/// let rt = runtime::Builder::new_multi_thread()
1193+
/// .enable_metrics_poll_count_histogram()
1194+
/// .metrics_poll_count_histogram_configuration(
1195+
/// HistogramConfiguration::linear(Duration::from_micros(10), 100)
1196+
/// )
1197+
/// .build()
1198+
/// .unwrap();
1199+
/// ```
1200+
///
1201+
/// Configure a [`LogHistogram`] with the following settings:
1202+
/// - Measure times from 100ns to 120s
1203+
/// - Max error of 0.1
1204+
/// - No more than 1024 buckets
1205+
/// ```
1206+
/// use std::time::Duration;
1207+
/// use tokio::runtime;
1208+
/// use tokio::runtime::{HistogramConfiguration, LogHistogram};
1209+
///
1210+
/// let rt = runtime::Builder::new_multi_thread()
1211+
/// .enable_metrics_poll_count_histogram()
1212+
/// .metrics_poll_count_histogram_configuration(
1213+
/// HistogramConfiguration::log(LogHistogram::builder()
1214+
/// .max_value(Duration::from_secs(120))
1215+
/// .min_value(Duration::from_nanos(100))
1216+
/// .max_error(0.1)
1217+
/// .max_buckets(1024)
1218+
/// .expect("configuration uses 488 buckets")
1219+
/// )
1220+
/// )
1221+
/// .build()
1222+
/// .unwrap();
1223+
/// ```
1224+
///
1225+
/// [`LogHistogram`]: crate::runtime::LogHistogram
1226+
/// [default configuration]: crate::runtime::LogHistogramBuilder
1227+
pub fn metrics_poll_count_histogram_configuration(&mut self, configuration: HistogramConfiguration) -> &mut Self {
1228+
self.metrics_poll_count_histogram.histogram_type = configuration.inner;
11531229
self
11541230
}
11551231

@@ -1173,19 +1249,22 @@ impl Builder {
11731249
/// use tokio::runtime;
11741250
/// use std::time::Duration;
11751251
///
1252+
/// # #[allow(deprecated)]
11761253
/// let rt = runtime::Builder::new_multi_thread()
11771254
/// .enable_metrics_poll_count_histogram()
11781255
/// .metrics_poll_count_histogram_resolution(Duration::from_micros(100))
11791256
/// .build()
11801257
/// .unwrap();
11811258
/// ```
1259+
#[deprecated(note = "use metrics_poll_count_histogram_configuration")]
11821260
pub fn metrics_poll_count_histogram_resolution(&mut self, resolution: Duration) -> &mut Self {
11831261
assert!(resolution > Duration::from_secs(0));
11841262
// Sanity check the argument and also make the cast below safe.
11851263
assert!(resolution <= Duration::from_secs(1));
11861264

11871265
let resolution = resolution.as_nanos() as u64;
1188-
self.metrics_poll_count_histogram.resolution = resolution;
1266+
1267+
self.metrics_poll_count_histogram.legacy_mut(|b|b.resolution = resolution);
11891268
self
11901269
}
11911270

@@ -1204,14 +1283,16 @@ impl Builder {
12041283
/// ```
12051284
/// use tokio::runtime;
12061285
///
1286+
/// # #[allow(deprecated)]
12071287
/// let rt = runtime::Builder::new_multi_thread()
12081288
/// .enable_metrics_poll_count_histogram()
12091289
/// .metrics_poll_count_histogram_buckets(15)
12101290
/// .build()
12111291
/// .unwrap();
12121292
/// ```
1293+
#[deprecated(note = "use `metrics_poll_count_histogram_configuration")]
12131294
pub fn metrics_poll_count_histogram_buckets(&mut self, buckets: usize) -> &mut Self {
1214-
self.metrics_poll_count_histogram.num_buckets = buckets;
1295+
self.metrics_poll_count_histogram.legacy_mut(|b|b.num_buckets = buckets);
12151296
self
12161297
}
12171298
}

tokio/src/runtime/metrics/batch.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,6 @@ cfg_rt_multi_thread! {
171171
}
172172
}
173173

174-
fn duration_as_u64(dur: Duration) -> u64 {
174+
pub(crate) fn duration_as_u64(dur: Duration) -> u64 {
175175
u64::try_from(dur.as_nanos()).unwrap_or(u64::MAX)
176176
}

0 commit comments

Comments
 (0)