mod collapsed;
mod json;
mod markdown;
mod speedscope;
mod text;
pub use collapsed::*;
pub use json::*;
pub use markdown::*;
pub use speedscope::*;
pub use text::*;
use std::io::Write;
use thiserror::Error;
use crate::analysis::{CpuAnalysis, HeapAnalysis};
use crate::ir::ProfileIR;
#[derive(Debug, Error)]
pub enum OutputError {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("JSON serialization error: {0}")]
Json(#[from] serde_json::Error),
}
pub fn format_time_us(time_us: u64) -> String {
let ms = time_us as f64 / 1000.0;
format_time_ms(ms)
}
pub fn format_time_ms(ms: f64) -> String {
if ms < 1000.0 {
format!("{ms:.2} ms")
} else if ms < 60_000.0 {
format!("{:.2} s", ms / 1000.0)
} else {
format!("{:.2} min", ms / 60_000.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OutputFormat {
Markdown,
Text,
Json,
Speedscope,
Collapsed,
}
impl OutputFormat {
pub fn from_str(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"markdown" | "md" => Some(Self::Markdown),
"text" | "txt" => Some(Self::Text),
"json" => Some(Self::Json),
"speedscope" => Some(Self::Speedscope),
"collapsed" | "folded" => Some(Self::Collapsed),
_ => None,
}
}
pub fn extension(&self) -> &'static str {
match self {
Self::Markdown => "md",
Self::Text => "txt",
Self::Json => "json",
Self::Speedscope => "speedscope.json",
Self::Collapsed => "collapsed.txt",
}
}
pub fn default_filename(&self) -> &'static str {
match self {
Self::Markdown => "profile-analysis.md",
Self::Text => "profile-analysis.txt",
Self::Json => "profile-analysis.json",
Self::Speedscope => "profile.speedscope.json",
Self::Collapsed => "profile.collapsed.txt",
}
}
}
pub trait Formatter {
fn write_cpu_analysis(
&self,
profile: &ProfileIR,
analysis: &CpuAnalysis,
writer: &mut dyn Write,
) -> Result<(), OutputError>;
fn write_heap_analysis(
&self,
profile: &ProfileIR,
analysis: &HeapAnalysis,
writer: &mut dyn Write,
) -> Result<(), OutputError>;
}
pub fn get_formatter(format: OutputFormat) -> Box<dyn Formatter> {
match format {
OutputFormat::Markdown => Box::new(MarkdownFormatter),
OutputFormat::Text => Box::new(TextFormatter),
OutputFormat::Json => Box::new(JsonFormatter),
OutputFormat::Speedscope => Box::new(SpeedscopeFormatter),
OutputFormat::Collapsed => Box::new(CollapsedFormatter),
}
}