Skip to content

Commit d8bc02e

Browse files
authored
Fix updating of work packet statistics (#613)
Work packets can have different `TypeID`s but the same `work_name()` since work names strip type parameters whereas `TypeID`s don't. Hence, work packet statistics used to overwrite previously existing values leading to incorrect values of the `work.*.{count,max,min,total}` fields. This commit fixes this bug by correctly updating the values. This commit also closes #479 by converting the work packet times to milliseconds.
1 parent f78de4e commit d8bc02e

File tree

2 files changed

+40
-25
lines changed

2 files changed

+40
-25
lines changed

src/scheduler/stat.rs

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,20 @@ impl SchedulerStat {
4545
/// Used during statistics printing at [`crate::memory_manager::harness_end`]
4646
pub fn harness_stat(&self) -> HashMap<String, String> {
4747
let mut stat = HashMap::new();
48+
let mut counts = HashMap::<String, usize>::new();
49+
let mut times = HashMap::<String, f64>::new();
4850
// Work counts
4951
let mut total_count = 0;
5052
for (t, c) in &self.work_counts {
5153
total_count += c;
5254
let n = self.work_id_name_map[t];
53-
stat.insert(
54-
format!("work.{}.count", self.work_name(n)),
55-
format!("{}", c),
56-
);
55+
// We can have the same work names for different TypeIDs since work names strip
56+
// type parameters away, while the same work packet with different type parameters
57+
// are given different TypeIDs. Hence, we check if the key exists and update instead of
58+
// overwrite it
59+
let pkt = format!("work.{}.count", self.work_name(n));
60+
let val = counts.entry(pkt).or_default();
61+
*val += c;
5762
}
5863
stat.insert("total-work.count".to_owned(), format!("{}", total_count));
5964
// Work execution times
@@ -73,34 +78,44 @@ impl SchedulerStat {
7378
// Update the overall execution time
7479
duration_overall.merge_inplace(&fold);
7580
let name = v.first().unwrap().name();
76-
stat.insert(
77-
format!("work.{}.{}.total", self.work_name(n), name),
78-
format!("{:.2}", fold.total),
79-
);
80-
stat.insert(
81-
format!("work.{}.{}.min", self.work_name(n), name),
82-
format!("{:.2}", fold.min),
83-
);
84-
stat.insert(
85-
format!("work.{}.{}.max", self.work_name(n), name),
86-
format!("{:.2}", fold.max),
87-
);
81+
let pkt_total = format!("work.{}.{}.total", self.work_name(n), name);
82+
let pkt_min = format!("work.{}.{}.min", self.work_name(n), name);
83+
let pkt_max = format!("work.{}.{}.max", self.work_name(n), name);
84+
85+
// We can have the same work names for different TypeIDs since work names strip
86+
// type parameters away, while the same work packet with different type parameters
87+
// are given different TypeIDs. Hence, we check if the key exists and update
88+
// instead of overwrite it
89+
let val = times.entry(pkt_total).or_default();
90+
*val += fold.total;
91+
let val = times.entry(pkt_min).or_default();
92+
*val = f64::min(*val, fold.min);
93+
let val = times.entry(pkt_max).or_default();
94+
*val = f64::max(*val, fold.max);
8895
}
8996
}
90-
// Print out overall execution time
97+
// Convert to ms and print out overall execution time
9198
stat.insert(
9299
"total-work.time.total".to_owned(),
93-
format!("{:.2}", duration_overall.total),
100+
format!("{:.3}", duration_overall.total / 1e6),
94101
);
95102
stat.insert(
96103
"total-work.time.min".to_owned(),
97-
format!("{:.2}", duration_overall.min),
104+
format!("{:.3}", duration_overall.min / 1e6),
98105
);
99106
stat.insert(
100107
"total-work.time.max".to_owned(),
101-
format!("{:.2}", duration_overall.max),
108+
format!("{:.3}", duration_overall.max / 1e6),
102109
);
103110

111+
for (pkt, count) in counts {
112+
stat.insert(pkt, format!("{}", count));
113+
}
114+
115+
for (pkt, time) in times {
116+
stat.insert(pkt, format!("{:.3}", time / 1e6));
117+
}
118+
104119
stat
105120
}
106121
/// Merge work counters from different worker threads

src/scheduler/work_counter.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! work-packet level statistics
55
//!
66
//! See [`crate::util::statistics`] for collecting statistics over a GC cycle
7-
use std::time::SystemTime;
7+
use std::time::Instant;
88

99
/// Common struct for different work counters
1010
///
@@ -92,11 +92,11 @@ impl WorkCounterBase {
9292

9393
/// Measure the durations of work packets
9494
///
95-
/// Timing is based on [`SystemTime`]
95+
/// Timing is based on [`Instant`]
9696
#[derive(Copy, Clone, Debug)]
9797
pub(super) struct WorkDuration {
9898
base: WorkCounterBase,
99-
start_value: Option<SystemTime>,
99+
start_value: Option<Instant>,
100100
running: bool,
101101
}
102102

@@ -112,12 +112,12 @@ impl WorkDuration {
112112

113113
impl WorkCounter for WorkDuration {
114114
fn start(&mut self) {
115-
self.start_value = Some(SystemTime::now());
115+
self.start_value = Some(Instant::now());
116116
self.running = true;
117117
}
118118

119119
fn stop(&mut self) {
120-
let duration = self.start_value.unwrap().elapsed().unwrap().as_nanos() as f64;
120+
let duration = self.start_value.unwrap().elapsed().as_nanos() as f64;
121121
self.base.merge_val(duration);
122122
}
123123

0 commit comments

Comments
 (0)