|
| 1 | +use super::EXEC_HARNESS_COMMAND; |
| 2 | +use crate::prelude::*; |
| 3 | +use crate::project_config::Target; |
| 4 | +use crate::project_config::WalltimeOptions; |
| 5 | +use exec_harness::BenchmarkCommand; |
| 6 | + |
| 7 | +/// Convert targets from project config to exec-harness JSON input format |
| 8 | +pub fn targets_to_exec_harness_json( |
| 9 | + targets: &[Target], |
| 10 | + default_walltime: Option<&WalltimeOptions>, |
| 11 | +) -> Result<String> { |
| 12 | + let inputs: Vec<BenchmarkCommand> = targets |
| 13 | + .iter() |
| 14 | + .map(|target| { |
| 15 | + // Parse the exec string into command parts |
| 16 | + let command = shell_words::split(&target.exec) |
| 17 | + .with_context(|| format!("Failed to parse command: {}", target.exec))?; |
| 18 | + |
| 19 | + // Merge target-specific walltime options with defaults |
| 20 | + let target_walltime = target.options.as_ref().and_then(|o| o.walltime.as_ref()); |
| 21 | + let walltime_args = merge_walltime_options(default_walltime, target_walltime); |
| 22 | + |
| 23 | + Ok(BenchmarkCommand { |
| 24 | + command, |
| 25 | + name: target.name.clone(), |
| 26 | + walltime_args, |
| 27 | + }) |
| 28 | + }) |
| 29 | + .collect::<Result<Vec<_>>>()?; |
| 30 | + |
| 31 | + serde_json::to_string(&inputs).context("Failed to serialize targets to JSON") |
| 32 | +} |
| 33 | + |
| 34 | +/// Merge default walltime options with target-specific overrides |
| 35 | +fn merge_walltime_options( |
| 36 | + default: Option<&WalltimeOptions>, |
| 37 | + target: Option<&WalltimeOptions>, |
| 38 | +) -> exec_harness::walltime::WalltimeExecutionArgs { |
| 39 | + let default_args = default.map(walltime_options_to_args); |
| 40 | + let target_args = target.map(walltime_options_to_args); |
| 41 | + |
| 42 | + match (default_args, target_args) { |
| 43 | + (None, None) => exec_harness::walltime::WalltimeExecutionArgs::default(), |
| 44 | + (Some(d), None) => d, |
| 45 | + (None, Some(t)) => t, |
| 46 | + (Some(d), Some(t)) => exec_harness::walltime::WalltimeExecutionArgs { |
| 47 | + warmup_time: t.warmup_time.or(d.warmup_time), |
| 48 | + max_time: t.max_time.or(d.max_time), |
| 49 | + min_time: t.min_time.or(d.min_time), |
| 50 | + max_rounds: t.max_rounds.or(d.max_rounds), |
| 51 | + min_rounds: t.min_rounds.or(d.min_rounds), |
| 52 | + }, |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +/// Convert project config WalltimeOptions to exec-harness WalltimeExecutionArgs |
| 57 | +fn walltime_options_to_args( |
| 58 | + opts: &WalltimeOptions, |
| 59 | +) -> exec_harness::walltime::WalltimeExecutionArgs { |
| 60 | + exec_harness::walltime::WalltimeExecutionArgs { |
| 61 | + warmup_time: opts.warmup_time.clone(), |
| 62 | + max_time: opts.max_time.clone(), |
| 63 | + min_time: opts.min_time.clone(), |
| 64 | + max_rounds: opts.max_rounds, |
| 65 | + min_rounds: opts.min_rounds, |
| 66 | + } |
| 67 | +} |
| 68 | + |
| 69 | +/// Build a command that pipes targets JSON to exec-harness via stdin |
| 70 | +pub fn build_pipe_command( |
| 71 | + targets: &[Target], |
| 72 | + default_walltime: Option<&WalltimeOptions>, |
| 73 | +) -> Result<Vec<String>> { |
| 74 | + let json = targets_to_exec_harness_json(targets, default_walltime)?; |
| 75 | + // Use a heredoc to safely pass the JSON to exec-harness |
| 76 | + Ok(vec![ |
| 77 | + EXEC_HARNESS_COMMAND.to_owned(), |
| 78 | + "-".to_owned(), |
| 79 | + "<<".to_owned(), |
| 80 | + "'CODSPEED_EOF'\n".to_owned(), |
| 81 | + json, |
| 82 | + "\nCODSPEED_EOF".to_owned(), |
| 83 | + ]) |
| 84 | +} |
0 commit comments