use miden_core::operations::Operation;
mod op_histogram;
pub use op_histogram::OpHistogram;
pub trait Instrument {
fn name(&self) -> &'static str;
fn on_operation_execution_cycle(&mut self, op: Operation);
fn write_report_to(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()>;
}
pub trait InstrumentRegistration: Sized + Instrument + 'static {
const NAME: &'static str;
fn build(config: &super::ProfilerConfig) -> Result<Self, InstrumentError>;
}
#[derive(Debug, thiserror::Error)]
pub enum InstrumentError {
#[error("unknown profiling instrument '{0}'")]
Undefined(String),
#[error("failed to construct instrument '{name}': {reason}")]
Build { name: String, reason: String },
}
pub fn instrument_from_name(
name: &str,
config: &super::ProfilerConfig,
) -> Result<Box<dyn Instrument>, InstrumentError> {
for instrument in inventory::iter::<InstrumentRegistrationInfo>() {
if instrument.name == name {
return (instrument.builder)(config);
}
}
Err(InstrumentError::Undefined(name.to_string()))
}
#[doc(hidden)]
pub struct InstrumentRegistrationInfo {
name: &'static str,
builder: fn(&super::ProfilerConfig) -> Result<Box<dyn Instrument>, InstrumentError>,
}
impl InstrumentRegistrationInfo {
pub const fn new<T: InstrumentRegistration>() -> Self {
let name = <T as InstrumentRegistration>::NAME;
Self {
name,
builder: build_instrument::<T>,
}
}
}
#[macro_export]
macro_rules! register_instrument {
($t:ty) => {
inventory::submit!($crate::profiling::instrument::InstrumentRegistrationInfo::new::<$t>());
};
}
inventory::collect!(InstrumentRegistrationInfo);
#[inline]
fn build_instrument<T: InstrumentRegistration>(
config: &super::ProfilerConfig,
) -> Result<Box<dyn Instrument>, InstrumentError> {
<T as InstrumentRegistration>::build(config).map(|inst| Box::new(inst) as Box<dyn Instrument>)
}