mirror of
https://github.com/sharkdp/hyperfine.git
synced 2026-11-01 08:50:19 +00:00
Refine JSON schema and command metadata
This commit is contained in:
1 parent
c5d3a81fc5
commit
0d86e78ede
15 files changed
+59
-60
No files matched your search
@@ -9,18 +9,19 @@ use crate::quantity::Time;
|
||||
#[derive(Debug, Default, Clone, Serialize, PartialEq)]
|
||||
pub struct Parameter {
|
||||
pub value: String,
|
||||
#[serde(skip_serializing)]
|
||||
pub is_unused: bool,
|
||||
}
|
||||
|
||||
/// Meta data and performance metrics for a single benchmark
|
||||
#[derive(Debug, Default, Clone, Serialize, PartialEq)]
|
||||
pub struct BenchmarkResult {
|
||||
/// The display name of the command being benchmarked
|
||||
/// The expanded command line being benchmarked
|
||||
pub command: String,
|
||||
|
||||
/// The expanded command line, when it differs from the display name
|
||||
/// The display name, when it differs from the command line
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub command_raw: Option<String>,
|
||||
pub name: Option<String>,
|
||||
|
||||
/// Performance metric measurements and exit codes for each run
|
||||
#[serde(flatten)]
|
||||
@@ -32,12 +33,16 @@ pub struct BenchmarkResult {
|
||||
}
|
||||
|
||||
impl BenchmarkResult {
|
||||
pub fn get_name(&self) -> &str {
|
||||
self.name.as_deref().unwrap_or(&self.command)
|
||||
}
|
||||
|
||||
/// The average wall clock time
|
||||
pub fn mean_wall_clock_time(&self) -> Time {
|
||||
self.measurements.time_wall_clock_mean()
|
||||
}
|
||||
|
||||
/// The full command line of the program that is being benchmarked, possibly including a list of
|
||||
/// The display name of the command, possibly including a list of
|
||||
/// parameters that were not used in the command line template.
|
||||
pub fn command_with_unused_parameters(&self) -> String {
|
||||
let parameters = self
|
||||
@@ -54,6 +59,6 @@ impl BenchmarkResult {
|
||||
format!(" ({parameters})")
|
||||
};
|
||||
|
||||
format!("{}{}", self.command, parameters)
|
||||
format!("{}{}", self.get_name(), parameters)
|
||||
}
|
||||
}
|
||||
@@ -475,13 +475,13 @@ impl<'a> Benchmark<'a> {
|
||||
|
||||
self.run_cleanup_command(self.command.get_parameters().iter().cloned(), output_policy)?;
|
||||
|
||||
let command = self.command.get_name();
|
||||
let command_raw = self.command.get_command_line();
|
||||
let command_raw = (command_raw != command).then_some(command_raw);
|
||||
let command = self.command.get_command_line();
|
||||
let name = self.command.get_name();
|
||||
let name = (name != command).then_some(name);
|
||||
|
||||
Ok(BenchmarkResult {
|
||||
command,
|
||||
command_raw,
|
||||
name,
|
||||
measurements,
|
||||
parameters: self
|
||||
.command
|
||||
|
||||
@@ -158,7 +158,7 @@ fn create_result(name: &str, mean: f64) -> BenchmarkResult {
|
||||
|
||||
BenchmarkResult {
|
||||
command: name.into(),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements {
|
||||
measurements: vec![Measurement {
|
||||
time_wall_clock: Time::new::<second>(mean),
|
||||
|
||||
+4
-4
@@ -42,7 +42,7 @@ impl Exporter for CsvExporter {
|
||||
}
|
||||
|
||||
for res in results {
|
||||
let mut fields = vec![Cow::Borrowed(res.command.as_bytes())];
|
||||
let mut fields = vec![Cow::Borrowed(res.get_name().as_bytes())];
|
||||
for f in &[
|
||||
res.mean_wall_clock_time(),
|
||||
res.measurements.stddev().unwrap_or_default(),
|
||||
@@ -80,8 +80,8 @@ fn test_csv() {
|
||||
|
||||
let results = vec![
|
||||
BenchmarkResult {
|
||||
command: String::from("command_a"),
|
||||
command_raw: None,
|
||||
command: String::from("echo command_a"),
|
||||
name: Some(String::from("command_a")),
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(7.0),
|
||||
@@ -126,7 +126,7 @@ fn test_csv() {
|
||||
},
|
||||
BenchmarkResult {
|
||||
command: String::from("command_b"),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(17.0),
|
||||
|
||||
+10
-6
@@ -15,8 +15,11 @@ use anyhow::Result;
|
||||
mod metadata;
|
||||
use metadata::Metadata;
|
||||
|
||||
const JSON_SCHEMA_VERSION: u32 = 2;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct HyperfineSummary<'a> {
|
||||
schema_version: u32,
|
||||
metadata: &'a Metadata,
|
||||
results: Vec<JsonBenchmarkResult<'a>>,
|
||||
}
|
||||
@@ -116,6 +119,7 @@ impl Exporter for JsonExporter {
|
||||
_reference_index: Option<usize>,
|
||||
) -> Result<Vec<u8>> {
|
||||
let mut output = to_vec_pretty(&HyperfineSummary {
|
||||
schema_version: JSON_SCHEMA_VERSION,
|
||||
metadata: &self.metadata,
|
||||
results: results
|
||||
.iter()
|
||||
@@ -182,7 +186,7 @@ fn test_json_optional_memory() {
|
||||
] {
|
||||
let result = BenchmarkResult {
|
||||
command: "example".into(),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![Measurement {
|
||||
peak_memory_usage: memory,
|
||||
..Measurement::default()
|
||||
@@ -196,8 +200,8 @@ fn test_json_optional_memory() {
|
||||
.unwrap();
|
||||
let actual: serde_json::Value = serde_json::from_slice(&output).unwrap();
|
||||
let mut expected = json!({
|
||||
"schema_version": JSON_SCHEMA_VERSION,
|
||||
"metadata": {
|
||||
"json_schema_version": metadata::JSON_SCHEMA_VERSION,
|
||||
"hyperfine_version": env!("CARGO_PKG_VERSION"),
|
||||
"start_time": "2000-02-29T12:34:56Z",
|
||||
"platform": exporter.metadata.platform
|
||||
@@ -250,12 +254,12 @@ fn test_json_summaries_for_parameterized_results() {
|
||||
.into_iter()
|
||||
.map(|(size, times)| BenchmarkResult {
|
||||
command: "example".into(),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
parameters: [(
|
||||
"size".into(),
|
||||
Parameter {
|
||||
value: size.into(),
|
||||
is_unused: true,
|
||||
is_unused: size == "small",
|
||||
},
|
||||
)]
|
||||
.into(),
|
||||
@@ -276,8 +280,8 @@ fn test_json_summaries_for_parameterized_results() {
|
||||
let actual: serde_json::Value = serde_json::from_slice(&output).unwrap();
|
||||
let results = actual["results"].as_array().unwrap();
|
||||
assert_eq!(results.len(), 2);
|
||||
assert_eq!(results[0]["parameters"]["size"]["value"], "small");
|
||||
assert_eq!(results[1]["parameters"]["size"]["value"], "large");
|
||||
assert_eq!(results[0]["parameters"]["size"], json!({"value": "small"}));
|
||||
assert_eq!(results[1]["parameters"]["size"], json!({"value": "large"}));
|
||||
assert_eq!(results[0]["measurements"].as_array().unwrap().len(), 2);
|
||||
assert_eq!(results[1]["measurements"].as_array().unwrap().len(), 1);
|
||||
assert_eq!(
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use serde::Serialize;
|
||||
|
||||
pub(super) const JSON_SCHEMA_VERSION: u32 = 2;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub(super) struct Metadata {
|
||||
json_schema_version: u32,
|
||||
hyperfine_version: &'static str,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub start_time: Option<String>,
|
||||
@@ -14,7 +11,6 @@ pub(super) struct Metadata {
|
||||
impl Default for Metadata {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
json_schema_version: JSON_SCHEMA_VERSION,
|
||||
hyperfine_version: env!("CARGO_PKG_VERSION"),
|
||||
start_time: utc_now(),
|
||||
platform: Platform::detect(),
|
||||
|
||||
+8
-8
@@ -28,7 +28,7 @@ fn test_markup_export_auto_ms() {
|
||||
let results = [
|
||||
BenchmarkResult {
|
||||
command: String::from("sleep 0.1"),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(0.09),
|
||||
@@ -56,7 +56,7 @@ fn test_markup_export_auto_ms() {
|
||||
},
|
||||
BenchmarkResult {
|
||||
command: String::from("sleep 2"),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(2.0),
|
||||
@@ -129,7 +129,7 @@ fn test_markup_export_auto_s() {
|
||||
let results = [
|
||||
BenchmarkResult {
|
||||
command: String::from("sleep 2"),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(2.1),
|
||||
@@ -157,7 +157,7 @@ fn test_markup_export_auto_s() {
|
||||
},
|
||||
BenchmarkResult {
|
||||
command: String::from("sleep 0.1"),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(0.1),
|
||||
@@ -230,7 +230,7 @@ fn test_markup_export_manual_ms() {
|
||||
let timing_results = [
|
||||
BenchmarkResult {
|
||||
command: String::from("sleep 2"),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(2.1),
|
||||
@@ -258,7 +258,7 @@ fn test_markup_export_manual_ms() {
|
||||
},
|
||||
BenchmarkResult {
|
||||
command: String::from("sleep 0.1"),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(0.1),
|
||||
@@ -330,7 +330,7 @@ fn test_markup_export_manual_s() {
|
||||
let results = [
|
||||
BenchmarkResult {
|
||||
command: String::from("sleep 2"),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(2.01),
|
||||
@@ -358,7 +358,7 @@ fn test_markup_export_manual_s() {
|
||||
},
|
||||
BenchmarkResult {
|
||||
command: String::from("sleep 0.1"),
|
||||
command_raw: None,
|
||||
name: None,
|
||||
measurements: Measurements::new(vec![
|
||||
Measurement {
|
||||
time_wall_clock: Time::new::<second>(0.11),
|
||||
|
||||
Reference in new issue
Block a user