Skip to main content

miden_debug_engine/profiling/
config.rs

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