Skip to content

Commit 35efbf5

Browse files
bors[bot]matklad
andauthored
Merge #8244
8244: internal: track missing `.check_cancelled` r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 7b9e2a2 + 483a5bc commit 35efbf5

File tree

3 files changed

+81
-11
lines changed

3 files changed

+81
-11
lines changed

crates/base_db/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ pub trait CheckCanceled {
5959
Self: Sized + panic::RefUnwindSafe,
6060
F: FnOnce(&Self) -> T + panic::UnwindSafe,
6161
{
62+
// Uncomment to debug missing cancellations.
63+
// let _span = profile::heartbeat_span();
6264
panic::catch_unwind(|| f(self)).map_err(|err| match err.downcast::<Canceled>() {
6365
Ok(canceled) => *canceled,
6466
Err(payload) => panic::resume_unwind(payload),
@@ -68,6 +70,7 @@ pub trait CheckCanceled {
6870

6971
impl<T: salsa::Database> CheckCanceled for T {
7072
fn check_canceled(&self) {
73+
// profile::heartbeat();
7174
if self.salsa_runtime().is_current_revision_canceled() {
7275
Canceled::throw()
7376
}

crates/profile/src/hprof.rs

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,20 @@ pub fn span(label: Label) -> ProfileSpan {
6969
}
7070
}
7171

72+
#[inline]
73+
pub fn heartbeat_span() -> HeartbeatSpan {
74+
let enabled = PROFILING_ENABLED.load(Ordering::Relaxed);
75+
HeartbeatSpan::new(enabled)
76+
}
77+
78+
#[inline]
79+
pub fn heartbeat() {
80+
let enabled = PROFILING_ENABLED.load(Ordering::Relaxed);
81+
if enabled {
82+
with_profile_stack(|it| it.heartbeat(1));
83+
}
84+
}
85+
7286
pub struct ProfileSpan(Option<ProfilerImpl>);
7387

7488
struct ProfilerImpl {
@@ -92,6 +106,28 @@ impl Drop for ProfilerImpl {
92106
}
93107
}
94108

109+
pub struct HeartbeatSpan {
110+
enabled: bool,
111+
}
112+
113+
impl HeartbeatSpan {
114+
#[inline]
115+
pub fn new(enabled: bool) -> Self {
116+
if enabled {
117+
with_profile_stack(|it| it.heartbeats(true))
118+
}
119+
Self { enabled }
120+
}
121+
}
122+
123+
impl Drop for HeartbeatSpan {
124+
fn drop(&mut self) {
125+
if self.enabled {
126+
with_profile_stack(|it| it.heartbeats(false))
127+
}
128+
}
129+
}
130+
95131
static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false);
96132
static FILTER: Lazy<RwLock<Filter>> = Lazy::new(Default::default);
97133

@@ -105,6 +141,7 @@ struct Filter {
105141
depth: usize,
106142
allowed: HashSet<String>,
107143
longer_than: Duration,
144+
heartbeat_longer_than: Duration,
108145
version: usize,
109146
}
110147

@@ -121,6 +158,7 @@ impl Filter {
121158
} else {
122159
Duration::new(0, 0)
123160
};
161+
let heartbeat_longer_than = longer_than;
124162

125163
let depth = if let Some(idx) = spec.rfind('@') {
126164
let depth: usize = spec[idx + 1..].parse().expect("invalid profile depth");
@@ -131,7 +169,7 @@ impl Filter {
131169
};
132170
let allowed =
133171
if spec == "*" { HashSet::new() } else { spec.split('|').map(String::from).collect() };
134-
Filter { depth, allowed, longer_than, version: 0 }
172+
Filter { depth, allowed, longer_than, heartbeat_longer_than, version: 0 }
135173
}
136174

137175
fn install(mut self) {
@@ -143,9 +181,15 @@ impl Filter {
143181
}
144182

145183
struct ProfileStack {
146-
starts: Vec<Instant>,
184+
frames: Vec<Frame>,
147185
filter: Filter,
148186
messages: Tree<Message>,
187+
heartbeats: bool,
188+
}
189+
190+
struct Frame {
191+
t: Instant,
192+
heartbeats: u32,
149193
}
150194

151195
#[derive(Default)]
@@ -157,35 +201,49 @@ struct Message {
157201

158202
impl ProfileStack {
159203
fn new() -> ProfileStack {
160-
ProfileStack { starts: Vec::new(), messages: Tree::default(), filter: Default::default() }
204+
ProfileStack {
205+
frames: Vec::new(),
206+
messages: Tree::default(),
207+
filter: Default::default(),
208+
heartbeats: false,
209+
}
161210
}
162211

163212
fn push(&mut self, label: Label) -> bool {
164-
if self.starts.is_empty() {
213+
if self.frames.is_empty() {
165214
if let Ok(f) = FILTER.try_read() {
166215
if f.version > self.filter.version {
167216
self.filter = f.clone();
168217
}
169218
};
170219
}
171-
if self.starts.len() > self.filter.depth {
220+
if self.frames.len() > self.filter.depth {
172221
return false;
173222
}
174223
let allowed = &self.filter.allowed;
175-
if self.starts.is_empty() && !allowed.is_empty() && !allowed.contains(label) {
224+
if self.frames.is_empty() && !allowed.is_empty() && !allowed.contains(label) {
176225
return false;
177226
}
178227

179-
self.starts.push(Instant::now());
228+
self.frames.push(Frame { t: Instant::now(), heartbeats: 0 });
180229
self.messages.start();
181230
true
182231
}
183232

184233
fn pop(&mut self, label: Label, detail: Option<String>) {
185-
let start = self.starts.pop().unwrap();
186-
let duration = start.elapsed();
234+
let frame = self.frames.pop().unwrap();
235+
let duration = frame.t.elapsed();
236+
237+
if self.heartbeats {
238+
self.heartbeat(frame.heartbeats);
239+
let avg_span = duration / (frame.heartbeats + 1);
240+
if avg_span > self.filter.heartbeat_longer_than {
241+
eprintln!("Too few heartbeats {} ({}/{:?})?", label, frame.heartbeats, duration)
242+
}
243+
}
244+
187245
self.messages.finish(Message { duration, label, detail });
188-
if self.starts.is_empty() {
246+
if self.frames.is_empty() {
189247
let longer_than = self.filter.longer_than;
190248
// Convert to millis for comparison to avoid problems with rounding
191249
// (otherwise we could print `0ms` despite user's `>0` filter when
@@ -198,6 +256,15 @@ impl ProfileStack {
198256
self.messages.clear();
199257
}
200258
}
259+
260+
fn heartbeats(&mut self, yes: bool) {
261+
self.heartbeats = yes;
262+
}
263+
fn heartbeat(&mut self, n: u32) {
264+
if let Some(frame) = self.frames.last_mut() {
265+
frame.heartbeats += n;
266+
}
267+
}
201268
}
202269

203270
fn print(

crates/profile/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod tree;
1010
use std::cell::RefCell;
1111

1212
pub use crate::{
13-
hprof::{init, init_from, span},
13+
hprof::{heartbeat, heartbeat_span, init, init_from, span},
1414
memory_usage::{Bytes, MemoryUsage},
1515
stop_watch::{StopWatch, StopWatchSpan},
1616
};

0 commit comments

Comments
 (0)