use std::collections::HashMap;
use std::io::Write;
use crate::analysis::{CpuAnalysis, HeapAnalysis};
use crate::ir::ProfileIR;
use super::{Formatter, OutputError};
pub struct CollapsedFormatter;
impl Formatter for CollapsedFormatter {
fn write_cpu_analysis(
&self,
profile: &ProfileIR,
_analysis: &CpuAnalysis,
writer: &mut dyn Write,
) -> Result<(), OutputError> {
let mut stack_weights: HashMap<String, u64> = HashMap::new();
for sample in &profile.samples {
if let Some(stack) = profile.get_stack(sample.stack_id) {
let stack_str: String = stack
.frames
.iter()
.filter_map(|fid| {
profile.get_frame(*fid).map(|f| {
let name = if f.name.is_empty() {
"(anonymous)".to_string()
} else {
f.name.replace(';', ":")
};
if let Some(ref file) = f.file {
let filename = file.rsplit('/').next().unwrap_or(file);
if let Some(line) = f.line {
format!("{name} ({filename}:{line})")
} else {
format!("{name} ({filename})")
}
} else {
name
}
})
})
.collect::<Vec<_>>()
.join(";");
if !stack_str.is_empty() {
*stack_weights.entry(stack_str).or_default() += sample.weight;
}
}
}
let mut stacks: Vec<_> = stack_weights.into_iter().collect();
stacks.sort_by(|a, b| a.0.cmp(&b.0));
for (stack, weight) in stacks {
writeln!(writer, "{stack} {weight}")?;
}
Ok(())
}
fn write_heap_analysis(
&self,
profile: &ProfileIR,
_analysis: &HeapAnalysis,
writer: &mut dyn Write,
) -> Result<(), OutputError> {
let mut stack_weights: HashMap<String, u64> = HashMap::new();
for sample in &profile.samples {
if let Some(stack) = profile.get_stack(sample.stack_id) {
let stack_str: String = stack
.frames
.iter()
.filter_map(|fid| {
profile.get_frame(*fid).map(|f| {
let name = if f.name.is_empty() {
"(anonymous)".to_string()
} else {
f.name.replace(';', ":")
};
if let Some(ref file) = f.file {
let filename = file.rsplit('/').next().unwrap_or(file);
if let Some(line) = f.line {
format!("{name} ({filename}:{line})")
} else {
format!("{name} ({filename})")
}
} else {
name
}
})
})
.collect::<Vec<_>>()
.join(";");
if !stack_str.is_empty() {
*stack_weights.entry(stack_str).or_default() += sample.weight;
}
}
}
let mut stacks: Vec<_> = stack_weights.into_iter().collect();
stacks.sort_by(|a, b| a.0.cmp(&b.0));
for (stack, weight) in stacks {
writeln!(writer, "{stack} {weight}")?;
}
Ok(())
}
}