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