From a453a998aa829f44360965e39bac8ec7b00eb2b8 Mon Sep 17 00:00:00 2001 From: Matt Mastracci Date: Fri, 26 Jan 2024 11:46:48 -0500 Subject: [PATCH] feat(core): more enhancements to the stats API (#492) Add an op_exclusions filter and keep op names as `&'static str`. --- .../op_driver/futures_unordered_driver.rs | 8 +++- core/runtime/op_driver/joinset_driver.rs | 3 +- core/runtime/op_driver/mod.rs | 5 ++- core/runtime/stats.rs | 43 +++++++++++-------- testing/checkin/runner/ops.rs | 2 +- 5 files changed, 39 insertions(+), 22 deletions(-) diff --git a/core/runtime/op_driver/futures_unordered_driver.rs b/core/runtime/op_driver/futures_unordered_driver.rs index 3b7601ba4..a85ed5639 100644 --- a/core/runtime/op_driver/futures_unordered_driver.rs +++ b/core/runtime/op_driver/futures_unordered_driver.rs @@ -7,6 +7,7 @@ use super::OpInflightStats; use crate::OpId; use crate::PromiseId; use anyhow::Error; +use bit_set::BitSet; use deno_unsync::spawn; use deno_unsync::JoinHandle; use deno_unsync::UnsyncWaker; @@ -229,11 +230,14 @@ impl OpDriver for FuturesUnorderedDriver { self.len.get() } - fn stats(&self) -> OpInflightStats { + fn stats(&self, op_exclusions: &BitSet) -> OpInflightStats { let q = self.queue.queue.queue.borrow(); let mut v: Vec = Vec::with_capacity(self.len.get()); for f in q.iter() { - v.push(f.context()) + let context = f.context(); + if !op_exclusions.contains(context.1 as _) { + v.push(context); + } } OpInflightStats { ops: v.into_boxed_slice(), diff --git a/core/runtime/op_driver/joinset_driver.rs b/core/runtime/op_driver/joinset_driver.rs index 171127ddf..93ba335ec 100644 --- a/core/runtime/op_driver/joinset_driver.rs +++ b/core/runtime/op_driver/joinset_driver.rs @@ -5,6 +5,7 @@ use super::OpInflightStats; use crate::OpId; use crate::PromiseId; use anyhow::Error; +use bit_set::BitSet; use deno_unsync::JoinSet; use futures::task::noop_waker_ref; use futures::FutureExt; @@ -155,7 +156,7 @@ impl OpDriver for JoinSetDriver { self.pending_ops.borrow().len() } - fn stats(&self) -> OpInflightStats { + fn stats(&self, _op_exclusions: &BitSet) -> OpInflightStats { OpInflightStats::default() } } diff --git a/core/runtime/op_driver/mod.rs b/core/runtime/op_driver/mod.rs index 5422d9d85..f20b73019 100644 --- a/core/runtime/op_driver/mod.rs +++ b/core/runtime/op_driver/mod.rs @@ -2,6 +2,7 @@ use crate::OpId; use crate::PromiseId; use anyhow::Error; +use bit_set::BitSet; use std::future::Future; use std::task::Context; use std::task::Poll; @@ -134,8 +135,10 @@ pub(crate) trait OpDriver: /// may not be a cheap operation and calling it large number of times (for example, in an /// event loop) may cause slowdowns. /// + /// If `op_exclusions` is passed to this function, any ops in the set are excluded from the stats. + /// /// A [`PromiseId`] will appear in this list until its results have been picked up in `poll_ready`. - fn stats(&self) -> OpInflightStats; + fn stats(&self, op_exclusions: &BitSet) -> OpInflightStats; } #[cfg(test)] diff --git a/core/runtime/stats.rs b/core/runtime/stats.rs index 8bee3b335..66700266c 100644 --- a/core/runtime/stats.rs +++ b/core/runtime/stats.rs @@ -2,6 +2,7 @@ use super::op_driver::OpDriver; use super::op_driver::OpInflightStats; use super::ContextState; +use crate::OpId; use crate::OpState; use crate::PromiseId; use crate::ResourceId; @@ -17,11 +18,12 @@ pub struct RuntimeActivityStatsFactory { } /// Selects the statistics that you are interested in capturing. -#[derive(Clone, Copy, Default, PartialEq, Eq)] +#[derive(Clone, Default, PartialEq, Eq)] pub struct RuntimeActivityStatsFilter { include_timers: bool, include_ops: bool, include_resources: bool, + op_filter: BitSet, } impl RuntimeActivityStatsFilter { @@ -30,6 +32,7 @@ impl RuntimeActivityStatsFilter { include_ops: true, include_resources: true, include_timers: true, + op_filter: BitSet::default(), } } @@ -48,15 +51,28 @@ impl RuntimeActivityStatsFilter { self } + pub fn omit_op(mut self, op: OpId) -> Self { + self.op_filter.insert(op as _); + self + } + pub fn is_empty(&self) -> bool { - *self == Self::default() + // This ensures we don't miss a newly-added field in the empty comparison + let Self { + include_ops, + include_resources, + include_timers, + op_filter: _, + } = self; + !(*include_ops) && !(*include_resources) && !(*include_timers) } } impl RuntimeActivityStatsFactory { + /// Capture the current runtime activity. pub fn capture( self, - filter: RuntimeActivityStatsFilter, + filter: &RuntimeActivityStatsFilter, ) -> RuntimeActivityStats { let resources = if filter.include_resources { let res = &self.op_state.borrow().resource_table; @@ -91,7 +107,7 @@ impl RuntimeActivityStatsFactory { }; let ops = if filter.include_ops { - self.context_state.pending_ops.stats() + self.context_state.pending_ops.stats(&filter.op_filter) } else { OpInflightStats::default() }; @@ -131,7 +147,7 @@ pub struct RuntimeActivityStats { #[derive(Debug, Serialize)] pub enum RuntimeActivity { /// An async op, including the promise ID and op name. - AsyncOp(PromiseId, String), + AsyncOp(PromiseId, &'static str), /// A resource, including the resource ID and name. Resource(ResourceId, String), /// A timer, including the timer ID. @@ -173,10 +189,7 @@ impl RuntimeActivityStats { ); let ops = self.context_state.op_ctxs.borrow(); for op in self.ops.ops.iter() { - v.push(RuntimeActivity::AsyncOp( - op.0, - ops[op.1 as usize].decl.name.to_owned(), - )); + v.push(RuntimeActivity::AsyncOp(op.0, ops[op.1 as usize].decl.name)); } for resource in self.resources.resources.iter() { v.push(RuntimeActivity::Resource(resource.0, resource.1.clone())) @@ -205,19 +218,15 @@ impl RuntimeActivityStats { // continuing op } else { // before, but not after - disappeared.push(RuntimeActivity::AsyncOp( - op.0, - ops[op.1 as usize].decl.name.to_owned(), - )); + disappeared + .push(RuntimeActivity::AsyncOp(op.0, ops[op.1 as usize].decl.name)); } } for op in after.ops.ops.iter() { if a.contains(op.0 as usize) { // after but not before - appeared.push(RuntimeActivity::AsyncOp( - op.0, - ops[op.1 as usize].decl.name.to_owned(), - )); + appeared + .push(RuntimeActivity::AsyncOp(op.0, ops[op.1 as usize].decl.name)); } } diff --git a/testing/checkin/runner/ops.rs b/testing/checkin/runner/ops.rs index d49610bb8..5acd4f23c 100644 --- a/testing/checkin/runner/ops.rs +++ b/testing/checkin/runner/ops.rs @@ -41,7 +41,7 @@ pub fn op_stats_capture(#[string] name: String, state: Rc>) { .borrow() .borrow::() .clone(); - let data = stats.capture(RuntimeActivityStatsFilter::all()); + let data = stats.capture(&RuntimeActivityStatsFilter::all()); let mut state = state.borrow_mut(); let test_data = state.borrow_mut::(); test_data.insert(name, data);