use std::collections::HashMap;
use linux_perf_data::{PerfFileReader, PerfFileRecord};
#[allow(unused)]
use linux_perf_event_reader::RecordType;
fn main() {
let stdin = std::io::stdin();
let PerfFileReader {
mut perf_file,
mut record_iter,
} = match PerfFileReader::parse_pipe(stdin) {
Ok(reader) => reader,
Err(e) => {
println!("ERROR when creating PerfFileReader: {:?}", e);
return;
}
};
if let Ok(Some(arch)) = perf_file.arch() {
println!("Arch: {arch}");
}
if let Ok(Some(cmdline)) = perf_file.cmdline() {
println!("CmdLine: {cmdline:?}");
}
if let Ok(Some(cpu_desc)) = perf_file.cpu_desc() {
println!("CPU Desc: {cpu_desc}");
}
if let Ok(Some(perf_version)) = perf_file.perf_version() {
println!("Perf version: {perf_version}");
}
if let Ok(Some(frequency)) = perf_file.clock_frequency() {
println!("Clock frequency: {frequency} ns per tick");
}
if let Ok(Some(clock_data)) = perf_file.clock_data() {
println!("Clock data: {clock_data:?}");
}
let features = perf_file.features();
let features: String = features
.iter()
.map(|f| format!("{f}"))
.collect::<Vec<_>>()
.join(", ");
println!("Features: {features}");
println!();
if let Ok(Some(simpleperf_meta_info)) = perf_file.simpleperf_meta_info() {
println!("Simpleperf meta info:");
for (k, v) in simpleperf_meta_info {
println!(" {k}: {v}");
}
println!();
}
if let Ok(Some(simpleperf_file_symbols)) = perf_file.simpleperf_symbol_tables() {
println!("Simpleperf symbol tables for the following files:");
for f in &simpleperf_file_symbols {
println!(" - {}", f.path);
}
println!();
}
let mut event_record_map = HashMap::new();
let mut user_record_map = HashMap::new();
while let Some(record) = record_iter.next_record(&mut perf_file).unwrap() {
match record {
PerfFileRecord::EventRecord { attr_index, record } => {
let record_type = record.record_type;
*event_record_map
.entry(attr_index)
.or_insert_with(HashMap::new)
.entry(record_type)
.or_insert(0) += 1;
match record.parse() {
Ok(parsed_record) => {
let is_interesting = false;
if !is_interesting {
continue;
}
if let Some(timestamp) =
record.common_data().ok().and_then(|cd| cd.timestamp)
{
println!(
"{:?} at {} for event {}: {:?}",
record_type, timestamp, attr_index, parsed_record
);
} else {
println!(
"{:?} for event {}: {:?}",
record_type, attr_index, parsed_record
);
}
}
Err(e) => {
println!(
"ERROR when parsing {:?} for event {}: {:?}",
record_type, attr_index, e
);
}
}
}
PerfFileRecord::UserRecord(record) => {
let record_type = record.record_type;
*user_record_map.entry(record_type).or_insert(0) += 1;
match record.parse() {
Ok(_parsed_record) => {
}
Err(e) => {
println!("ERROR when parsing {:?}: {:?}", record_type, e);
}
}
}
}
}
let mut event_record_map = event_record_map
.into_iter()
.map(|(attr_index, histogram)| {
let sum = histogram.values().sum::<u64>();
(attr_index, histogram, sum)
})
.collect::<Vec<_>>();
event_record_map.sort_by_key(|(_attr_index, _histogram, sum)| -(*sum as i64));
let sum = event_record_map
.iter()
.map(|(_attr_index, _histogram, sum)| sum)
.sum::<u64>();
println!("Event records: {sum} records");
println!();
for (attr_index, record_counts, sum) in event_record_map {
let mut record_counts = record_counts.into_iter().collect::<Vec<_>>();
record_counts.sort_by_key(|(_record_type, count)| -(*count as i64));
println!(
" event {} ({}): {} records",
attr_index,
perf_file.event_attributes()[attr_index]
.name()
.unwrap_or("<no event name found>"),
sum
);
for (record_type, count) in record_counts {
println!(" {:?}: {}", record_type, count);
}
println!();
}
let mut user_record_counts = user_record_map.into_iter().collect::<Vec<_>>();
user_record_counts.sort_by_key(|(_record_type, count)| -(*count as i64));
let sum = user_record_counts
.iter()
.map(|(_record_type, count)| count)
.sum::<u64>();
println!("User records: {sum} records");
println!();
for (record_type, count) in user_record_counts {
println!(" {:?}: {}", record_type, count);
}
}