Skip to content

Commit 409cc2e

Browse files
committed
Sort scopes by first call time in output
1 parent 4de66c7 commit 409cc2e

1 file changed

Lines changed: 56 additions & 34 deletions

File tree

splashsurf_lib/src/profiling.rs

Lines changed: 56 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ struct Scope {
8282
name: &'static str,
8383
num_calls: usize,
8484
duration_sum: Duration,
85+
first_call: Instant,
8586
}
8687

8788
impl Scope {
@@ -90,13 +91,17 @@ impl Scope {
9091
name,
9192
num_calls: 0,
9293
duration_sum: Default::default(),
94+
first_call: Instant::now(),
9395
}
9496
}
9597

9698
fn merge(&mut self, other: &Self) {
9799
if other.name == self.name {
98100
self.num_calls += other.num_calls;
99101
self.duration_sum += other.duration_sum;
102+
if other.first_call < self.first_call {
103+
self.first_call = other.first_call;
104+
}
100105
}
101106
}
102107
}
@@ -180,39 +185,40 @@ impl Profiler {
180185

181186
fn write_recursively<W: io::Write>(
182187
out: &mut W,
183-
scopes: &HashMap<ScopeId, Scope>,
184-
id: &ScopeId,
188+
sorted_scopes: &[(ScopeId, Scope)],
189+
current: &(ScopeId, Scope),
185190
total_duration: Option<Duration>,
186191
depth: usize,
187192
) -> io::Result<()> {
188-
if let Some(scope) = scopes.get(id) {
189-
let current_hash = ScopeId::get_hash(Some(id));
193+
let (id, scope) = current;
190194

191-
for _ in 0..depth {
192-
write!(out, " ")?;
193-
}
195+
for _ in 0..depth {
196+
write!(out, " ")?;
197+
}
194198

195-
let duration_sum_secs = scope.duration_sum.as_secs_f64();
196-
let total_duration_secs = total_duration.map_or(duration_sum_secs, |t| t.as_secs_f64());
197-
let percent = duration_sum_secs / total_duration_secs * 100.0;
198-
199-
writeln!(
200-
out,
201-
"{}: {:3.2}%, {:>4.2}ms avg @ {:.2}Hz ({} {})",
202-
scope.name,
203-
percent,
204-
duration_sum_secs * 1000.0 / (scope.num_calls as f64),
205-
scope.num_calls as f64 / total_duration_secs,
206-
scope.num_calls,
207-
if scope.num_calls > 1 { "calls" } else { "call" }
208-
)?;
209-
210-
// TODO: Prevent infinite recursion for recursive functions, maybe remove current scope from map?
211-
// Maybe we don't have this problem, instead it will be a huge chain which is as long as the recursion depth...
212-
for child_id in scopes.keys() {
213-
if child_id.parent_hash == current_hash {
214-
write_recursively(out, scopes, child_id, Some(scope.duration_sum), depth + 1)?;
215-
}
199+
let duration_sum_secs = scope.duration_sum.as_secs_f64();
200+
let total_duration_secs = total_duration.map_or(duration_sum_secs, |t| t.as_secs_f64());
201+
let percent = duration_sum_secs / total_duration_secs * 100.0;
202+
203+
writeln!(
204+
out,
205+
"{}: {:3.2}%, {:>4.2}ms avg @ {:.2}Hz ({} {})",
206+
scope.name,
207+
percent,
208+
duration_sum_secs * 1000.0 / (scope.num_calls as f64),
209+
scope.num_calls as f64 / total_duration_secs,
210+
scope.num_calls,
211+
if scope.num_calls > 1 { "calls" } else { "call" }
212+
)?;
213+
214+
// Process children in sorted order
215+
let current_hash = ScopeId::get_hash(Some(id));
216+
for s in sorted_scopes {
217+
let (child_id, _) = s;
218+
if child_id.parent_hash == current_hash {
219+
// TODO: Prevent infinite recursion for recursive functions, maybe remove current scope from map?
220+
// Maybe we don't have this problem, instead it will be a huge chain which is as long as the recursion depth...
221+
write_recursively(out, sorted_scopes, s, Some(scope.duration_sum), depth + 1)?;
216222
}
217223
}
218224

@@ -238,15 +244,31 @@ pub fn write<W: io::Write>(out: &mut W) -> io::Result<()> {
238244
}
239245
}
240246

241-
// Remove roots that are not actual roots (happens if their parent was set manually)
242-
{
247+
// Sort and filter root scopes
248+
let sorted_roots = {
243249
let root_hash = ScopeId::get_hash(None);
244-
roots.retain(|id| id.parent_hash == root_hash);
245-
}
250+
let mut roots = roots
251+
.into_iter()
252+
// Remove roots that are not actual roots (happens if their parent was set manually)
253+
.filter(|id| id.parent_hash == root_hash)
254+
// Get (id, scope) tuple
255+
.flat_map(|id| merged_scopes.get(&id).cloned().map(|s| (id, s)))
256+
.collect::<Vec<_>>();
257+
258+
roots.sort_unstable_by_key(|(_, s)| s.first_call);
259+
roots
260+
};
261+
262+
// Sort all scopes by first call time
263+
let sorted_scopes = {
264+
let mut scopes = merged_scopes.into_iter().collect::<Vec<_>>();
265+
scopes.sort_unstable_by_key(|(_, s)| s.first_call);
266+
scopes
267+
};
246268

247269
// Print the stats
248-
for root_id in &roots {
249-
write_recursively(out, &merged_scopes, root_id, None, 0)?;
270+
for root in &sorted_roots {
271+
write_recursively(out, sorted_scopes.as_slice(), root, None, 0)?;
250272
}
251273

252274
Ok(())

0 commit comments

Comments
 (0)