Skip to content

Commit 85eb154

Browse files
fix(criterion_fork): fix assertion failed: !(range.0.is_nan() || range.1.is_nan()) error
1 parent 1bd1b2e commit 85eb154

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

crates/criterion_compat/criterion_fork/src/plot/gnuplot_backend/summary.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,14 @@ pub fn line_comparison(
6565

6666
let mut i = 0;
6767

68+
// CODSPEED FIX: Changed from fold(::std::f64::NAN, f64::max) to fold(0.0, f64::max)
69+
// and added filter(|x| x.is_finite()) to prevent NaN propagation. See the same fix
70+
// in plotters_backend/summary.rs for detailed explanation.
6871
let max = all_curves
6972
.iter()
7073
.map(|&(_, data)| Sample::new(data).mean())
71-
.fold(::std::f64::NAN, f64::max);
74+
.filter(|x| x.is_finite())
75+
.fold(0.0, f64::max);
7276

7377
let mut dummy = [1.0];
7478
let unit = formatter.scale_values(max, &mut dummy);

crates/criterion_compat/criterion_fork/src/plot/plotters_backend/summary.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,19 @@ fn line_comparison_series_data<'a>(
118118
formatter: &dyn ValueFormatter,
119119
all_curves: &[&(&'a BenchmarkId, Vec<f64>)],
120120
) -> (&'static str, Vec<(Option<&'a String>, Vec<f64>, Vec<f64>)>) {
121+
// CODSPEED FIX: Changed from fold(::std::f64::NAN, f64::max) to fold(0.0, f64::max)
122+
// and added filter(|x| x.is_finite()) to prevent NaN propagation.
123+
//
124+
// Previously, starting the fold with NaN meant that f64::max would always return NaN
125+
// (since NaN comparisons always return false). This caused plotters to panic with
126+
// "assertion failed: !(range.0.is_nan() || range.1.is_nan())" when trying to create
127+
// plot ranges. This was particularly problematic with very small measurements (picoseconds)
128+
// and high outlier percentages, which could occur intermittently in CI.
121129
let max = all_curves
122130
.iter()
123131
.map(|&(_, data)| Sample::new(data).mean())
124-
.fold(::std::f64::NAN, f64::max);
132+
.filter(|x| x.is_finite())
133+
.fold(0.0, f64::max);
125134

126135
let mut dummy = [1.0];
127136
let unit = formatter.scale_values(max, &mut dummy);
@@ -166,8 +175,14 @@ pub fn violin(
166175
.map(|&&(id, ref sample)| {
167176
let (x, mut y) = kde::sweep(Sample::new(sample), KDE_POINTS, None);
168177
let y_max = Sample::new(&y).max();
169-
for y in y.iter_mut() {
170-
*y /= y_max;
178+
// CODSPEED FIX: Only normalize if y_max is finite and non-zero to prevent
179+
// division by zero or NaN propagation. Previously, dividing by y_max without
180+
// checking could produce Inf or NaN values if y_max was 0.0 or non-finite,
181+
// which would cause plotters to panic when creating plot ranges.
182+
if y_max.is_finite() && y_max > 0.0 {
183+
for y in y.iter_mut() {
184+
*y /= y_max;
185+
}
171186
}
172187

173188
(id.as_title(), x, y)

0 commit comments

Comments
 (0)