Skip to main content

miden_debug_engine/profiling/
config.rs

1use std::path::PathBuf;
2
3use miden_assembly_syntax::diagnostics::Report;
4
5use crate::profiling::{instrument::Instrument, instrument_from_name};
6
7/// Profiler options parsed from the command line.
8#[derive(Default, Clone, Debug, clap::Args)]
9pub struct ProfilerCliArgs {
10    /// Enables profiling and sets the output dir for reports. Profiling
11    /// instruments need to be enabled separately.
12    #[arg(long = "profiling-reports-dir", value_name = "DIRECTORY")]
13    pub reports_dir: Option<PathBuf>,
14    #[arg(
15        long = "profiling-instruments",
16        value_name = "VALUE",
17        value_delimiter = ','
18    )]
19    pub instruments: Vec<String>,
20}
21
22#[derive(Default)]
23pub struct ProfilerConfig {
24    /// The active instrumentations.
25    pub instruments: Vec<Box<dyn Instrument>>,
26    /// The directory where profiling reports are written.
27    pub reports_dir: Option<PathBuf>,
28}
29
30impl TryFrom<ProfilerCliArgs> for ProfilerConfig {
31    type Error = Report;
32
33    fn try_from(mut args: ProfilerCliArgs) -> Result<Self, Self::Error> {
34        let mut config = ProfilerConfig::default();
35
36        if let Some(ref path) = args.reports_dir
37            && path.exists()
38            && !path.is_dir()
39        {
40            return Err(Report::msg(format!(
41                "invalid profiling reports directory '{}': not a directory",
42                path.display()
43            )));
44        }
45
46        if args.reports_dir.is_some() && args.instruments.is_empty() {
47            return Err(Report::msg(
48                "profiling requires at least one instrument set with --profiling-instruments",
49            ));
50        }
51
52        if args.reports_dir.is_none() && !args.instruments.is_empty() {
53            return Err(Report::msg(
54                "profiling instruments require --profiling-reports-dir to be set",
55            ));
56        }
57
58        config.reports_dir = args.reports_dir;
59
60        args.instruments.sort();
61        args.instruments.dedup();
62        for name in &args.instruments {
63            let instrument = instrument_from_name(name, &config).map_err(Report::msg)?;
64            config.instruments.push(instrument);
65        }
66
67        Ok(config)
68    }
69}
70
71impl std::fmt::Debug for ProfilerConfig {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        let instrument_names: Vec<&'static str> =
74            self.instruments.iter().map(|i| i.name()).collect();
75        f.debug_struct("ProfilerConfig")
76            .field("instruments", &instrument_names)
77            .field("reports_dir", &self.reports_dir)
78            .finish()
79    }
80}