diff --git a/Cargo.lock b/Cargo.lock index 7864aba..0010ab9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,27 +99,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "borsh" @@ -226,7 +214,7 @@ dependencies = [ name = "clap_lex" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" [[package]] name = "colorchoice" @@ -340,12 +328,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "getrandom" version = "0.2.17" @@ -405,7 +387,7 @@ dependencies = [ "nix", "once_cell", "predicates", - "rand", + "rand 0.10.3", "rust_decimal", "serde", "serde_json", @@ -413,7 +395,7 @@ dependencies = [ "tempfile", "thiserror", "uom", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -635,13 +617,34 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -651,7 +654,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -663,6 +676,21 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "regex" version = "1.13.1" @@ -702,8 +730,8 @@ dependencies = [ "borsh", "bytes", "num-traits", - "rand", - "rkyv", + "rand 0.8.8", + "rand 0.9.5", "serde", "serde_json", "wasm-bindgen", @@ -789,6 +817,15 @@ version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +[[package]] +name = "strip-ansi-escapes" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.11.1" @@ -888,14 +925,8 @@ dependencies = [ ] [[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.13" +name = "toml_parser" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ @@ -920,6 +951,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "uom" version = "0.36.0" @@ -961,10 +998,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "windows-sys" -version = "0.48.0" +name = "wasip2" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" dependencies = [ "cfg-if", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index d779d03..e0e33e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ windows_process_extensions_main_thread_handle = [] colored = "3.1" # Newer versions regress ETA estimates: https://github.com/console-rs/indicatif/issues/580 indicatif = "=0.17.4" -csv = "1.3" +csv = "1.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" rust_decimal = "1.43" @@ -28,11 +28,7 @@ rand = "0.10" shell-words = "1.1" thiserror = "2.0" anyhow = "1.0" -uom = { version = "0.36.0", default-features = false, features = [ - "std", - "si", - "f64", -] } +uom = { version = "0.36.0", default-features = false, features = ["std", "si", "f64"] } [target.'cfg(not(windows))'.dependencies] libc = "0.2" diff --git a/src/benchmark/executor.rs b/src/benchmark/executor.rs index acdb3e5..5ffd27a 100644 --- a/src/benchmark/executor.rs +++ b/src/benchmark/executor.rs @@ -79,28 +79,15 @@ fn run_command_and_measure_common( let measurement = execute_and_measure(command) .with_context(|| format!("Failed to run command '{command_name}'"))?; - if command_failure_action == CmdFailureAction::RaiseError && !measurement.exit_status.success() - { - let when = match iteration { - BenchmarkIteration::NonBenchmarkRun => "a non-benchmark run".to_string(), - BenchmarkIteration::Warmup(0) => "the first warmup run".to_string(), - BenchmarkIteration::Warmup(i) => format!("warmup iteration {i}"), - BenchmarkIteration::Benchmark(0) => "the first benchmark run".to_string(), - BenchmarkIteration::Benchmark(i) => format!("benchmark iteration {i}"), - }; - bail!( - "{cause} in {when}. Use the '-i'/'--ignore-failure' option if you want to ignore this. \ - Alternatively, use the '--show-output' option to debug what went wrong.", - cause=measurement.exit_status.code().map_or( - "The process has been terminated by a signal".into(), - |c| format!("Command terminated with non-zero exit code {c}") + if !measurement.exit_status.success() { + use crate::util::exit_code::extract_exit_code; let should_fail = match command_failure_action { CmdFailureAction::RaiseError => true, CmdFailureAction::IgnoreAllFailures => false, CmdFailureAction::IgnoreSpecificFailures(ref codes) => { // Only fail if the exit code is not in the list of codes to ignore - if let Some(exit_code) = extract_exit_code(result.exit_status) { + if let Some(exit_code) = extract_exit_code(measurement.exit_status) { !codes.contains(&exit_code) } else { // If we can't extract an exit code, treat it as a failure @@ -120,7 +107,7 @@ fn run_command_and_measure_common( bail!( "{cause} in {when}. Use the '-i'/'--ignore-failure' option if you want to ignore this. \ Alternatively, use the '--show-output' option to debug what went wrong.", - cause=result.exit_status.code().map_or( + cause=measurement.exit_status.code().map_or( "The process has been terminated by a signal".into(), |c| format!("Command terminated with non-zero exit code {c}") diff --git a/src/benchmark/measurement.rs b/src/benchmark/measurement.rs index 8dc109d..186d4f4 100644 --- a/src/benchmark/measurement.rs +++ b/src/benchmark/measurement.rs @@ -115,8 +115,4 @@ impl Measurements { pub fn peak_memory_usage_mean(&self) -> Information { mean(self.measurements.iter().map(|m| m.peak_memory_usage)) } - - pub fn peak_memory_usage_mean(&self) -> Information { - mean(self.measurements.iter().map(|m| m.peak_memory_usage)) - } } diff --git a/src/benchmark/mod.rs b/src/benchmark/mod.rs index a2d7709..7f1ff51 100644 --- a/src/benchmark/mod.rs +++ b/src/benchmark/mod.rs @@ -379,8 +379,10 @@ impl<'a> Benchmark<'a> { let system_str = measurements.time_system_mean().format(time_unit); if self.options.output_style != OutputStyleOption::Disabled { + let mut stdout = io::stdout().lock(); if measurements.len() == 1 { - println!( + console_writeln!( + stdout, " Time ({} ≡): {:>8} {:>8} [User: {}, System: {}]", "abs".green().bold(), mean_str.green().bold(), diff --git a/src/benchmark/scheduler.rs b/src/benchmark/scheduler.rs index d0153da..0621555 100644 --- a/src/benchmark/scheduler.rs +++ b/src/benchmark/scheduler.rs @@ -93,7 +93,7 @@ impl<'a> Scheduler<'a> { stdout, " {} ran", reference.result.command_with_unused_parameters().cyan() - ); + )?; for item in others { let stddev = if let Some(stddev) = item.relative_speed_stddev { @@ -123,7 +123,7 @@ impl<'a> Scheduler<'a> { "{} {}", comparator, &item.result.command_with_unused_parameters().magenta() - ); + )?; } } SortOrder::Command => { diff --git a/src/export/mod.rs b/src/export/mod.rs index c82675e..0d3c67d 100644 --- a/src/export/mod.rs +++ b/src/export/mod.rs @@ -18,6 +18,7 @@ use self::orgmode::OrgmodeExporter; use crate::benchmark::benchmark_result::BenchmarkResult; use crate::options::SortOrder; +use crate::output::console_writeln; use crate::quantity::TimeUnit; use anyhow::{Context, Result}; diff --git a/src/timer/unix_timer.rs b/src/timer/unix_timer.rs index c6d7850..699a541 100644 --- a/src/timer/unix_timer.rs +++ b/src/timer/unix_timer.rs @@ -37,32 +37,37 @@ fn wait4(mut child: Child) -> io::Result<(ExitStatus, ResourceUsage)> { let mut status = 0; let mut rusage = MaybeUninit::zeroed(); - let result = unsafe { libc::wait4(pid, &mut status, 0, rusage.as_mut_ptr()) }; - - if result < 0 { - Err(io::Error::last_os_error()) - } else { - let rusage = unsafe { rusage.assume_init() }; - - let memory_usage_byte = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { - // Linux and *BSD return the value in KibiBytes, Darwin flavors in bytes - // A f64 can represent integers up to 2^53 exactly, so we can represent - // all values up to 2^53 bytes = 8 PiB exactly. Beyond that, our precision - // is larger than 1 byte, but that's considered acceptable. - Information::new::(rusage.ru_maxrss as f64) - } else { - Information::new::(rusage.ru_maxrss as f64) - }; - - Ok(( - ExitStatus::from_raw(status), - ResourceUsage { - time_user: convert_timeval(rusage.ru_utime), - time_system: convert_timeval(rusage.ru_stime), - memory_usage: memory_usage_byte.into(), - }, - )) + loop { + let result = unsafe { libc::wait4(pid, &mut status, 0, rusage.as_mut_ptr()) }; + if result >= 0 { + break; + } + let error = io::Error::last_os_error(); + if error.kind() != io::ErrorKind::Interrupted { + return Err(error); + } } + + let rusage = unsafe { rusage.assume_init() }; + + let memory_usage_byte = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { + // Linux and *BSD return the value in KibiBytes, Darwin flavors in bytes + // A f64 can represent integers up to 2^53 exactly, so we can represent + // all values up to 2^53 bytes = 8 PiB exactly. Beyond that, our precision + // is larger than 1 byte, but that's considered acceptable. + Information::new::(rusage.ru_maxrss as f64) + } else { + Information::new::(rusage.ru_maxrss as f64) + }; + + Ok(( + ExitStatus::from_raw(status), + ResourceUsage { + time_user: convert_timeval(rusage.ru_utime), + time_system: convert_timeval(rusage.ru_stime), + memory_usage: memory_usage_byte.into(), + }, + )) } pub struct CPUTimer {}