mirror of
https://github.com/sharkdp/hyperfine.git
synced 2026-11-02 17:11:28 +00:00
Use wait4 instead of getrusage
This commit is contained in:
1 parent
50232feb22
commit
ae0035ad56
9 files changed
+143
-98
No files matched your search
@@ -18,6 +18,12 @@ pub struct BenchmarkRun {
|
|||||||
|
|
||||||
/// Time spent in kernel mode
|
/// Time spent in kernel mode
|
||||||
pub system_time: Second,
|
pub system_time: Second,
|
||||||
|
|
||||||
|
/// Maximum memory usage of the process, in bytes
|
||||||
|
pub memory_usage_byte: u64,
|
||||||
|
|
||||||
|
/// Exit codes of the process
|
||||||
|
pub exit_code: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::benchmark::measurement::Measurements;
|
use crate::benchmark::measurement::Measurements;
|
||||||
@@ -45,13 +51,6 @@ pub struct BenchmarkResult {
|
|||||||
/// All run time measurements
|
/// All run time measurements
|
||||||
pub runs: Vec<BenchmarkRun>,
|
pub runs: Vec<BenchmarkRun>,
|
||||||
|
|
||||||
/// Maximum memory usage of the process, in bytes
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub memory_usage_byte: Option<Vec<u64>>,
|
|
||||||
|
|
||||||
/// Exit codes of all command invocations
|
|
||||||
pub exit_codes: Vec<Option<i32>>,
|
|
||||||
|
|
||||||
/// Parameter values for this benchmark
|
/// Parameter values for this benchmark
|
||||||
pub parameters: BTreeMap<String, Parameter>,
|
pub parameters: BTreeMap<String, Parameter>,
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-8
@@ -492,15 +492,25 @@ impl<'a> Benchmark<'a> {
|
|||||||
command_with_unused_parameters: self.command.get_name_with_unused_parameters(),
|
command_with_unused_parameters: self.command.get_name_with_unused_parameters(),
|
||||||
runs: times_real
|
runs: times_real
|
||||||
.iter()
|
.iter()
|
||||||
.zip(times_user.iter().zip(times_system.iter()))
|
.zip(times_user.iter())
|
||||||
.map(|(wall_clock_time, (user_time, system_time))| BenchmarkRun {
|
.zip(times_system.iter())
|
||||||
wall_clock_time: *wall_clock_time,
|
.zip(memory_usage_byte.iter())
|
||||||
user_time: *user_time,
|
.zip(exit_codes.iter())
|
||||||
system_time: *system_time,
|
.map(
|
||||||
})
|
|(
|
||||||
|
(((wall_clock_time, user_time), system_time), memory_usage_byte),
|
||||||
|
exit_code,
|
||||||
|
)| {
|
||||||
|
BenchmarkRun {
|
||||||
|
wall_clock_time: *wall_clock_time,
|
||||||
|
user_time: *user_time,
|
||||||
|
system_time: *system_time,
|
||||||
|
memory_usage_byte: *memory_usage_byte,
|
||||||
|
exit_code: *exit_code,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
.collect(),
|
.collect(),
|
||||||
memory_usage_byte: Some(memory_usage_byte),
|
|
||||||
exit_codes,
|
|
||||||
parameters: self
|
parameters: self
|
||||||
.command
|
.command
|
||||||
.get_parameters()
|
.get_parameters()
|
||||||
|
|||||||
@@ -156,9 +156,9 @@ fn create_result(name: &str, mean: f64) -> BenchmarkResult {
|
|||||||
wall_clock_time: mean,
|
wall_clock_time: mean,
|
||||||
user_time: mean,
|
user_time: mean,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
}],
|
}],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: Vec::new(),
|
|
||||||
parameters: BTreeMap::new(),
|
parameters: BTreeMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,29 +209,25 @@ fn scheduler_basic() -> Result<()> {
|
|||||||
- wall_clock_time: 0.123
|
- wall_clock_time: 0.123
|
||||||
user_time: 0
|
user_time: 0
|
||||||
system_time: 0
|
system_time: 0
|
||||||
|
memory_usage_byte: 0
|
||||||
|
exit_code: 0
|
||||||
- wall_clock_time: 0.123
|
- wall_clock_time: 0.123
|
||||||
user_time: 0
|
user_time: 0
|
||||||
system_time: 0
|
system_time: 0
|
||||||
memory_usage_byte:
|
memory_usage_byte: 0
|
||||||
- 0
|
exit_code: 0
|
||||||
- 0
|
|
||||||
exit_codes:
|
|
||||||
- 0
|
|
||||||
- 0
|
|
||||||
- command: sleep 0.456
|
- command: sleep 0.456
|
||||||
runs:
|
runs:
|
||||||
- wall_clock_time: 0.456
|
- wall_clock_time: 0.456
|
||||||
user_time: 0
|
user_time: 0
|
||||||
system_time: 0
|
system_time: 0
|
||||||
|
memory_usage_byte: 0
|
||||||
|
exit_code: 0
|
||||||
- wall_clock_time: 0.456
|
- wall_clock_time: 0.456
|
||||||
user_time: 0
|
user_time: 0
|
||||||
system_time: 0
|
system_time: 0
|
||||||
memory_usage_byte:
|
memory_usage_byte: 0
|
||||||
- 0
|
exit_code: 0
|
||||||
- 0
|
|
||||||
exit_codes:
|
|
||||||
- 0
|
|
||||||
- 0
|
|
||||||
"#);
|
"#);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
+12
-4
@@ -90,20 +90,24 @@ fn test_csv() {
|
|||||||
wall_clock_time: 7.0,
|
wall_clock_time: 7.0,
|
||||||
user_time: 7.0,
|
user_time: 7.0,
|
||||||
system_time: 0.0,
|
system_time: 0.0,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 8.0,
|
wall_clock_time: 8.0,
|
||||||
user_time: 8.0,
|
user_time: 8.0,
|
||||||
system_time: 0.0,
|
system_time: 0.0,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 12.0,
|
wall_clock_time: 12.0,
|
||||||
user_time: 12.0,
|
user_time: 12.0,
|
||||||
system_time: 0.0,
|
system_time: 0.0,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: {
|
parameters: {
|
||||||
let mut params = BTreeMap::new();
|
let mut params = BTreeMap::new();
|
||||||
params.insert(
|
params.insert(
|
||||||
@@ -131,20 +135,24 @@ fn test_csv() {
|
|||||||
wall_clock_time: 17.0,
|
wall_clock_time: 17.0,
|
||||||
user_time: 17.0,
|
user_time: 17.0,
|
||||||
system_time: 0.0,
|
system_time: 0.0,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 18.0,
|
wall_clock_time: 18.0,
|
||||||
user_time: 18.0,
|
user_time: 18.0,
|
||||||
system_time: 0.0,
|
system_time: 0.0,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 19.0,
|
wall_clock_time: 19.0,
|
||||||
user_time: 19.0,
|
user_time: 19.0,
|
||||||
system_time: 0.0,
|
system_time: 0.0,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: {
|
parameters: {
|
||||||
let mut params = BTreeMap::new();
|
let mut params = BTreeMap::new();
|
||||||
params.insert(
|
params.insert(
|
||||||
|
|||||||
+48
-16
@@ -33,20 +33,24 @@ fn test_markup_export_auto_ms() {
|
|||||||
wall_clock_time: 0.09,
|
wall_clock_time: 0.09,
|
||||||
user_time: 0.09,
|
user_time: 0.09,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 0.10,
|
wall_clock_time: 0.10,
|
||||||
user_time: 0.10,
|
user_time: 0.10,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 0.14,
|
wall_clock_time: 0.14,
|
||||||
user_time: 0.14,
|
user_time: 0.14,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: BTreeMap::new(),
|
parameters: BTreeMap::new(),
|
||||||
},
|
},
|
||||||
BenchmarkResult {
|
BenchmarkResult {
|
||||||
@@ -57,20 +61,24 @@ fn test_markup_export_auto_ms() {
|
|||||||
wall_clock_time: 2.0,
|
wall_clock_time: 2.0,
|
||||||
user_time: 2.0,
|
user_time: 2.0,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 3.0,
|
wall_clock_time: 3.0,
|
||||||
user_time: 3.0,
|
user_time: 3.0,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 4.0,
|
wall_clock_time: 4.0,
|
||||||
user_time: 4.0,
|
user_time: 4.0,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: BTreeMap::new(),
|
parameters: BTreeMap::new(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -126,20 +134,24 @@ fn test_markup_export_auto_s() {
|
|||||||
wall_clock_time: 2.1,
|
wall_clock_time: 2.1,
|
||||||
user_time: 2.1,
|
user_time: 2.1,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 2.2,
|
wall_clock_time: 2.2,
|
||||||
user_time: 2.2,
|
user_time: 2.2,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 2.3,
|
wall_clock_time: 2.3,
|
||||||
user_time: 2.3,
|
user_time: 2.3,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: BTreeMap::new(),
|
parameters: BTreeMap::new(),
|
||||||
},
|
},
|
||||||
BenchmarkResult {
|
BenchmarkResult {
|
||||||
@@ -150,20 +162,24 @@ fn test_markup_export_auto_s() {
|
|||||||
wall_clock_time: 0.1,
|
wall_clock_time: 0.1,
|
||||||
user_time: 0.1,
|
user_time: 0.1,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 0.2,
|
wall_clock_time: 0.2,
|
||||||
user_time: 0.2,
|
user_time: 0.2,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 0.3,
|
wall_clock_time: 0.3,
|
||||||
user_time: 0.3,
|
user_time: 0.3,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: BTreeMap::new(),
|
parameters: BTreeMap::new(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -219,20 +235,24 @@ fn test_markup_export_manual_ms() {
|
|||||||
wall_clock_time: 2.1,
|
wall_clock_time: 2.1,
|
||||||
user_time: 2.1,
|
user_time: 2.1,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 2.2,
|
wall_clock_time: 2.2,
|
||||||
user_time: 2.2,
|
user_time: 2.2,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 2.3,
|
wall_clock_time: 2.3,
|
||||||
user_time: 2.3,
|
user_time: 2.3,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: BTreeMap::new(),
|
parameters: BTreeMap::new(),
|
||||||
},
|
},
|
||||||
BenchmarkResult {
|
BenchmarkResult {
|
||||||
@@ -243,20 +263,24 @@ fn test_markup_export_manual_ms() {
|
|||||||
wall_clock_time: 0.1,
|
wall_clock_time: 0.1,
|
||||||
user_time: 0.1,
|
user_time: 0.1,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 0.2,
|
wall_clock_time: 0.2,
|
||||||
user_time: 0.2,
|
user_time: 0.2,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 0.3,
|
wall_clock_time: 0.3,
|
||||||
user_time: 0.3,
|
user_time: 0.3,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: BTreeMap::new(),
|
parameters: BTreeMap::new(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -311,20 +335,24 @@ fn test_markup_export_manual_s() {
|
|||||||
wall_clock_time: 2.01,
|
wall_clock_time: 2.01,
|
||||||
user_time: 2.01,
|
user_time: 2.01,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 2.02,
|
wall_clock_time: 2.02,
|
||||||
user_time: 2.02,
|
user_time: 2.02,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 2.03,
|
wall_clock_time: 2.03,
|
||||||
user_time: 2.03,
|
user_time: 2.03,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: BTreeMap::new(),
|
parameters: BTreeMap::new(),
|
||||||
},
|
},
|
||||||
BenchmarkResult {
|
BenchmarkResult {
|
||||||
@@ -335,20 +363,24 @@ fn test_markup_export_manual_s() {
|
|||||||
wall_clock_time: 0.11,
|
wall_clock_time: 0.11,
|
||||||
user_time: 0.11,
|
user_time: 0.11,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 0.12,
|
wall_clock_time: 0.12,
|
||||||
user_time: 0.12,
|
user_time: 0.12,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
BenchmarkRun {
|
BenchmarkRun {
|
||||||
wall_clock_time: 0.13,
|
wall_clock_time: 0.13,
|
||||||
user_time: 0.13,
|
user_time: 0.13,
|
||||||
system_time: 0.,
|
system_time: 0.,
|
||||||
|
memory_usage_byte: 1024,
|
||||||
|
exit_code: Some(0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
memory_usage_byte: None,
|
|
||||||
exit_codes: vec![Some(0), Some(0), Some(0)],
|
|
||||||
parameters: BTreeMap::new(),
|
parameters: BTreeMap::new(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
+13
-2
@@ -24,6 +24,17 @@ use std::process::{ChildStdout, Command};
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
/// Used to indicate the result of running a command
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct TimerResult {
|
||||||
|
pub time_real: Second,
|
||||||
|
pub time_user: Second,
|
||||||
|
pub time_system: Second,
|
||||||
|
pub memory_usage_byte: u64,
|
||||||
|
/// The exit status of the process
|
||||||
|
pub status: ExitStatus,
|
||||||
|
}
|
||||||
|
|
||||||
/// Discard the output of a child process.
|
/// Discard the output of a child process.
|
||||||
fn discard(output: ChildStdout) {
|
fn discard(output: ChildStdout) {
|
||||||
const CHUNK_SIZE: usize = 64 << 10;
|
const CHUNK_SIZE: usize = 64 << 10;
|
||||||
@@ -82,8 +93,8 @@ pub fn execute_and_measure(mut command: Command) -> Result<Measurement> {
|
|||||||
discard(output);
|
discard(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (time_user, time_system, peak_memory_usage, exit_status) = cpu_timer.stop(child)?;
|
let (status, time_user, time_system, memory_usage_byte) = cpu_timer.stop(child)?;
|
||||||
let time_wall_clock = wallclock_timer.stop();
|
let time_real = wallclock_timer.stop();
|
||||||
|
|
||||||
Ok(Measurement {
|
Ok(Measurement {
|
||||||
time_wall_clock,
|
time_wall_clock,
|
||||||
|
|||||||
+32
-41
@@ -1,5 +1,6 @@
|
|||||||
#![cfg(not(windows))]
|
#![cfg(not(windows))]
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::os::unix::process::ExitStatusExt;
|
use std::os::unix::process::ExitStatusExt;
|
||||||
@@ -7,26 +8,24 @@ use std::process::{Child, ExitStatus};
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::quantity::{byte, kibibyte, microsecond, second, Information, Time};
|
use crate::util::units::Second;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
struct ResourceUsage {
|
struct ResourceUsage {
|
||||||
/// Total amount of time spent executing in user mode
|
/// Total amount of time spent executing in user mode
|
||||||
pub time_user: Time,
|
pub user_usec: Second,
|
||||||
|
|
||||||
/// Total amount of time spent executing in kernel mode
|
/// Total amount of time spent executing in kernel mode
|
||||||
pub time_system: Time,
|
pub system_usec: Second,
|
||||||
|
|
||||||
/// Maximum amount of memory used by the process, in bytes
|
/// Maximum amount of memory used by the process, in bytes
|
||||||
pub memory_usage: Information,
|
pub memory_usage_byte: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::useless_conversion)]
|
#[allow(clippy::useless_conversion)]
|
||||||
fn convert_timeval(tv: libc::timeval) -> Time {
|
fn timeval_to_seconds(tv: libc::timeval) -> Second {
|
||||||
let sec = tv.tv_sec as f64;
|
const MICROSEC_PER_SEC: i64 = 1000 * 1000;
|
||||||
let usec = tv.tv_usec as f64;
|
(i64::from(tv.tv_sec) * MICROSEC_PER_SEC + i64::from(tv.tv_usec)) as f64 * 1e-6
|
||||||
|
|
||||||
Time::new::<second>(sec) + Time::new::<microsecond>(usec)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::useless_conversion)]
|
#[allow(clippy::useless_conversion)]
|
||||||
@@ -37,37 +36,29 @@ fn wait4(mut child: Child) -> io::Result<(ExitStatus, ResourceUsage)> {
|
|||||||
let mut status = 0;
|
let mut status = 0;
|
||||||
let mut rusage = MaybeUninit::zeroed();
|
let mut rusage = MaybeUninit::zeroed();
|
||||||
|
|
||||||
loop {
|
let result = unsafe { libc::wait4(pid, &mut status, 0, rusage.as_mut_ptr()) };
|
||||||
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() };
|
if result < 0 {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
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::<byte>(rusage.ru_maxrss as f64)
|
|
||||||
} else {
|
} else {
|
||||||
Information::new::<kibibyte>(rusage.ru_maxrss as f64)
|
let rusage = unsafe { rusage.assume_init() };
|
||||||
};
|
|
||||||
|
|
||||||
Ok((
|
let memory_usage_byte = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
|
||||||
ExitStatus::from_raw(status),
|
// Linux and *BSD return the value in KibiBytes, Darwin flavors in bytes
|
||||||
ResourceUsage {
|
rusage.ru_maxrss
|
||||||
time_user: convert_timeval(rusage.ru_utime),
|
} else {
|
||||||
time_system: convert_timeval(rusage.ru_stime),
|
rusage.ru_maxrss * 1024
|
||||||
memory_usage: memory_usage_byte.into(),
|
};
|
||||||
},
|
|
||||||
))
|
Ok((
|
||||||
|
ExitStatus::from_raw(status),
|
||||||
|
ResourceUsage {
|
||||||
|
user_usec: timeval_to_seconds(rusage.ru_utime),
|
||||||
|
system_usec: timeval_to_seconds(rusage.ru_stime),
|
||||||
|
memory_usage_byte: memory_usage_byte.into(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CPUTimer {}
|
pub struct CPUTimer {}
|
||||||
@@ -77,13 +68,13 @@ impl CPUTimer {
|
|||||||
Self {}
|
Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop(&self, child: Child) -> Result<(Time, Time, Information, ExitStatus)> {
|
pub fn stop(&self, child: Child) -> Result<(ExitStatus, Second, Second, u64)> {
|
||||||
let (status, usage) = wait4(child)?;
|
let (status, usage) = wait4(child)?;
|
||||||
Ok((
|
Ok((
|
||||||
usage.time_user,
|
|
||||||
usage.time_system,
|
|
||||||
usage.memory_usage,
|
|
||||||
status,
|
status,
|
||||||
|
usage.user_usec,
|
||||||
|
usage.system_usec,
|
||||||
|
u64::try_from(usage.memory_usage_byte).unwrap_or(0),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ impl CPUTimer {
|
|||||||
Self { job_object }
|
Self { job_object }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop(&self, mut child: Child) -> Result<(Time, Time, Information, ExitStatus)> {
|
pub fn stop(&self, mut child: Child) -> Result<(ExitStatus, Second, Second, u64)> {
|
||||||
let status = child.wait()?;
|
let status = child.wait()?;
|
||||||
|
|
||||||
let mut job_object_info =
|
let mut job_object_info =
|
||||||
@@ -113,12 +113,10 @@ impl CPUTimer {
|
|||||||
// The `TotalKernelTime` is "The total amount of kernel-mode execution time
|
// The `TotalKernelTime` is "The total amount of kernel-mode execution time
|
||||||
// for all active processes associated with the job, as well as all terminated
|
// for all active processes associated with the job, as well as all terminated
|
||||||
// processes no longer associated with the job, in 100-nanosecond ticks."
|
// processes no longer associated with the job, in 100-nanosecond ticks."
|
||||||
let system_time =
|
let kernel: i64 = job_object_info.TotalKernelTime / HUNDRED_NS_PER_MS;
|
||||||
Time::new::<nanosecond>((job_object_info.TotalKernelTime as f64) * 100.0);
|
Ok((status, user as f64 * 1e-6, kernel as f64 * 1e-6, 0))
|
||||||
|
|
||||||
Ok((user_time, system_time, Information::zero(), status))
|
|
||||||
} else {
|
} else {
|
||||||
Ok((Time::zero(), Time::zero(), Information::zero(), status))
|
Ok((status, 0.0, 0.0, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user