Skip to content

Commit

Permalink
Add support for reporting throughput and elements simultaneously.
Browse files Browse the repository at this point in the history
Only hooked up for the CLI reporter for now, but it's pretty useful when
doing data processing to understand both throughput variants when you're
doing batch processing.
  • Loading branch information
vlovich committed Sep 13, 2023
1 parent 180f4b4 commit 32ef410
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Fixed
- Quick mode (--quick) no longer crashes with measured times over 5 seconds when --noplot is not active
- `Throughput::ElementsAndBytes` added to allow the text summary to report throughput in both units simultaneously.

## [0.5.0] - 2023-05-23

Expand Down
11 changes: 11 additions & 0 deletions benches/benchmarks/custom_measurement.rs
Expand Up @@ -21,6 +21,14 @@ impl ValueFormatter for HalfSecFormatter {
"{} elem/s/2",
(elems as f64) / (value * 2f64 * 10f64.powi(-9))
),
Throughput::ElementsAndBytes {
elements: _,
bytes: _,
} => format!(
"{} elem/s/2, {} b/s/2",
(elems as f64) / (value * 2f64 * 10f64.powi(-9),),
(bytes as f64) / (value * 2f64 * 10f64.powi(-9))
),
}
}

Expand Down Expand Up @@ -53,6 +61,9 @@ impl ValueFormatter for HalfSecFormatter {

"elem/s/2"
}
Throughput::ElementsAndBytes { elements, bytes: _ } => {
self.scale_throughputs(_typical, &Throughput::Elements(elements), values)
}
}
}

Expand Down
12 changes: 12 additions & 0 deletions benches/benchmarks/with_inputs.rs
Expand Up @@ -22,6 +22,18 @@ fn from_elem(c: &mut Criterion) {
});
}
group.finish();

let mut group = c.benchmark_group("from_elem_dual_throughput");
for size in [KB, 2 * KB].iter() {
group.throughput(Throughput::ElementsAndBytes {
elements: *size as u64,
bytes: 2 * *size as u64,
});
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
b.iter(|| iter::repeat(0u16).take(size).collect::<Vec<_>>());
});
}
group.finish();
}

criterion_group!(benches, from_elem);
3 changes: 3 additions & 0 deletions book/src/user_guide/advanced_configuration.md
Expand Up @@ -119,6 +119,9 @@ alloc time: [5.9846 ms 6.0192 ms 6.0623 ms]
thrpt: [164.95 MiB/s 166.14 MiB/s 167.10 MiB/s]
```

You can also request that the throughput measure both elements/s and bytes/s if, for example, you're doing some kind of data processing and
want to understand both the number of records/s and the total bytes/s achieved. This is achieved by setting `throughput` to `Throughput::ElementsAndBytes`.

## Chart Axis Scaling

By default, Criterion.rs generates plots using a linear-scale axis. When using parameterized benchmarks, it is common for the input sizes to scale exponentially in order to cover a wide range of possible inputs. In this situation, it may be easier to read the resulting plots with a logarithmic axis.
Expand Down
17 changes: 17 additions & 0 deletions src/lib.rs
Expand Up @@ -1293,6 +1293,23 @@ pub enum Throughput {
/// collection, but could also be the number of lines of input text or the number of values to
/// parse.
Elements(u64),

/// Measure throughput in terms of both elements/second and bytes/second. Typically,
/// this would be used if you have a collection of rows where `elements` would be the length of
/// the collection and `bytes` would be the total size of the collection if you're processing
/// the entire collection in one iteration. This will make sure the report simultaneously
/// includes on the rows/s and MB/s that data processing is able to achieve.
/// The elements are considered the "primary" throughput being reported on (i.e. what will appear
/// in the BenchmarkId).
ElementsAndBytes {
/// The value should be the number of elements processed by one iteration of the benchmarked code.
/// Typically, this would be the size of a collection, but could also be the number of lines of
/// input text or the number of values to parse.
elements: u64,
/// The value should be the number of bytes processed by one iteration of the benchmarked code.
/// Typically, this would be the length of an input string or `&[u8]`.
bytes: u64,
},
}

/// Axis scaling type
Expand Down
4 changes: 4 additions & 0 deletions src/measurement.rs
Expand Up @@ -182,6 +182,10 @@ impl ValueFormatter for DurationFormatter {
self.bytes_per_second_decimal(bytes as f64, typical, values)
}
Throughput::Elements(elems) => self.elements_per_second(elems as f64, typical, values),
// The caller should be formatting the bytes and elements separately.
Throughput::ElementsAndBytes { elements, bytes: _ } => {
self.elements_per_second(elements as f64, typical, values)
}
}
}

Expand Down
19 changes: 18 additions & 1 deletion src/report.rs
Expand Up @@ -176,6 +176,7 @@ impl BenchmarkId {
Some(Throughput::Bytes(n))
| Some(Throughput::Elements(n))
| Some(Throughput::BytesDecimal(n)) => Some(n as f64),
Some(Throughput::ElementsAndBytes { elements, bytes: _ }) => Some(elements as f64),
None => self
.value_str
.as_ref()
Expand All @@ -188,6 +189,10 @@ impl BenchmarkId {
Some(Throughput::Bytes(_)) => Some(ValueType::Bytes),
Some(Throughput::BytesDecimal(_)) => Some(ValueType::Bytes),
Some(Throughput::Elements(_)) => Some(ValueType::Elements),
Some(Throughput::ElementsAndBytes {
elements: _,
bytes: _,
}) => Some(ValueType::Elements),
None => self
.value_str
.as_ref()
Expand Down Expand Up @@ -577,7 +582,7 @@ impl Report for CliReport {
);
}

if let Some(ref throughput) = meas.throughput {
for ref throughput in measurement_throughputs(meas) {
println!(
"{}thrpt: [{} {} {}]",
" ".repeat(24),
Expand Down Expand Up @@ -790,6 +795,18 @@ fn compare_to_threshold(estimate: &Estimate, noise: f64) -> ComparisonResult {
}
}

fn measurement_throughputs(mes: &MeasurementData<'_>) -> Vec<Throughput> {
mes.throughput
.as_ref()
.map(|t| match t {
Throughput::ElementsAndBytes { elements, bytes } => {
vec![Throughput::Elements(*elements), Throughput::Bytes(*bytes)]
}
_ => vec![t.clone()],
})
.unwrap_or(vec![])
}

#[cfg(test)]
mod test {
use super::*;
Expand Down

0 comments on commit 32ef410

Please sign in to comment.