Skip to content

Commit

Permalink
Aperf: Allow to use custom PMU
Browse files Browse the repository at this point in the history
Allow the user to specify a custom PMU file to be used during aperf
record. This custom PMU file must be in the expected format.

To aid in the creation of the custom PMU file, add a sub-command.

'aperf custom-pmu' - an interactive sub-command to create custom PMU.
This allows the user to create a file from scratch or modify an existing
PMU config aperf already knows about. The custom file generated can be
used by specifying '--pmu-config' with 'aperf record'.
  • Loading branch information
janaknat committed Dec 23, 2024
1 parent 00705a5 commit e5b529b
Show file tree
Hide file tree
Showing 9 changed files with 457 additions and 5 deletions.
113 changes: 113 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ libc = "0.2"
flate2 = "1.0.30"
tar = "0.4.40"
infer = "0.13.0"
inquire = "0.7.5"
bincode = "1.3.3"
inferno = "0.11.19"
indexmap = "2.1.0"
Expand Down
5 changes: 5 additions & 0 deletions src/bin/aperf.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::Result;
use aperf::pmu::{custom_pmu, CustomPMU};
use aperf::record::{record, Record};
use aperf::report::{report, Report};
use aperf::{PDError, APERF_RUNLOG, APERF_TMP};
Expand Down Expand Up @@ -39,6 +40,9 @@ enum Commands {

/// Generate an HTML report based on the data collected.
Report(Report),

/// Create a custom PMU configuration file for use with Aperf record.
CustomPMU(CustomPMU),
}

fn init_logger(verbose: u8, runlog: &PathBuf) -> Result<()> {
Expand Down Expand Up @@ -98,6 +102,7 @@ fn main() -> Result<()> {
match cli.command {
Commands::Record(r) => record(&r, &tmp_dir_path_buf, &runlog),
Commands::Report(r) => report(&r, &tmp_dir_path_buf),
Commands::CustomPMU(r) => custom_pmu(&r),
}?;
fs::remove_dir_all(tmp_dir_path_buf)?;
Ok(())
Expand Down
3 changes: 3 additions & 0 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub struct CollectorParams {
pub tmp_dir: PathBuf,
pub signal: Signal,
pub runlog: PathBuf,
pub pmu_config: Option<PathBuf>,
}

impl CollectorParams {
Expand All @@ -70,6 +71,7 @@ impl CollectorParams {
tmp_dir: PathBuf::new(),
signal: signal::SIGTERM,
runlog: PathBuf::new(),
pmu_config: Option::None,
}
}
}
Expand Down Expand Up @@ -129,6 +131,7 @@ impl DataType {
self.collector_params.profile = param.profile.clone();
self.collector_params.tmp_dir = param.tmp_dir.clone();
self.collector_params.runlog = param.runlog.clone();
self.collector_params.pmu_config = param.pmu_config.clone();

self.file_handle = Some(
OpenOptions::new()
Expand Down
20 changes: 16 additions & 4 deletions src/data/perf_stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{PDError, PERFORMANCE_DATA, VISUALIZATION_DATA};
use anyhow::Result;
use chrono::prelude::*;
use ctor::ctor;
use log::{trace, warn};
use log::{error, info, trace, warn};
use perf_event::events::{Raw, Software};
use perf_event::{Builder, Counter, Group, ReadFormat};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -144,7 +144,7 @@ pub fn to_events(data: &[u8]) -> Result<Vec<NamedCtr>> {
}

impl CollectData for PerfStatRaw {
fn prepare_data_collector(&mut self, _params: &CollectorParams) -> Result<()> {
fn prepare_data_collector(&mut self, params: &CollectorParams) -> Result<()> {
let num_cpus = match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN as libc::c_int) } {
-1 => {
warn!("Could not get the number of cpus in the system with sysconf.");
Expand All @@ -156,7 +156,7 @@ impl CollectData for PerfStatRaw {

cfg_if::cfg_if! {
if #[cfg(target_arch = "aarch64")] {
let perf_list = to_events(arm64::perf_list::GRV_EVENTS)?;
let mut perf_list = to_events(arm64_perf_list::GRV_EVENTS)?;
} else if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
let cpu_info = crate::data::utils::get_cpu_info()?;
let platform_specific_counter: &[u8];
Expand Down Expand Up @@ -186,11 +186,23 @@ impl CollectData for PerfStatRaw {
return Err(PDError::CollectorPerfUnsupportedCPU.into());
}

let perf_list = form_events_map(base, platform_specific_counter)?;
let mut perf_list = form_events_map(base, platform_specific_counter)?;
} else {
return Err(PDError::CollectorPerfUnsupportedCPU.into());
}
}
if let Some(custom_file) = &params.pmu_config {
let f = std::fs::File::open(custom_file)?;
let user_provided_list: Vec<NamedCtr> = serde_json::from_reader(&f)?;
if user_provided_list.is_empty() {
error!(
"User provided PMU configuration is invalid. Falling back to default events."
);
} else {
info!("Using custom PMU configuration provided by user.");
perf_list = user_provided_list;
}
}
for cpu in 0..num_cpus {
for named_ctr in &perf_list {
let perf_group = Builder::new(Software::DUMMY)
Expand Down
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
extern crate lazy_static;

pub mod data;
pub mod pmu;
pub mod record;
pub mod report;
pub mod visualizer;
Expand Down Expand Up @@ -94,6 +95,9 @@ pub enum PDError {
#[error("File not found {}", .0)]
VisualizerFileNotFound(String),

#[error("Custom PMU config file not provided.")]
PMUCustomFileNotFound,

#[error("Run data not available")]
InvalidRunData,

Expand Down Expand Up @@ -530,6 +534,7 @@ pub struct InitParams {
pub dir_name: String,
pub period: u64,
pub profile: HashMap<String, String>,
pub pmu_config: Option<PathBuf>,
pub interval: u64,
pub run_name: String,
pub collector_version: String,
Expand Down Expand Up @@ -568,6 +573,7 @@ impl InitParams {
dir_name,
period: 0,
profile: HashMap::new(),
pmu_config: Option::None,
interval: 0,
run_name,
collector_version,
Expand Down
Loading

0 comments on commit e5b529b

Please sign in to comment.