in src/data/perf_stat.rs [150:315]
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.");
return Err(PDError::CollectorPMUCPUError.into());
}
ret => ret as usize,
};
let mut cpu_groups: Vec<CpuCtrGroup> = Vec::new();
cfg_if::cfg_if! {
if #[cfg(target_arch = "aarch64")] {
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];
let base: &[u8];
/* Get Vendor Specific Perf events */
if cpu_info.vendor == "GenuineIntel" {
base = x86_perf_list::INTEL_EVENTS;
/* Get Model specific events */
platform_specific_counter = match cpu_info.model_name.as_str() {
"Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz" => x86_perf_list::ICX_CTRS,
"Intel(R) Xeon(R) Platinum 8488C" => x86_perf_list::SPR_CTRS,
_ => &[0; 1],
};
} else if cpu_info.vendor == "AuthenticAMD" {
warn!("Event multiplexing may result in bad PMU data."); //TODO: mitigate bad PMU data on AMD instances
base = x86_perf_list::AMD_EVENTS;
/* Get Model specific events */
platform_specific_counter = match cpu_info.model_name.get(..13).unwrap_or_default() {
"AMD EPYC 9R14" => x86_perf_list::GENOA_CTRS,
"AMD EPYC 7R13" => x86_perf_list::MILAN_CTRS,
_ => &[0; 1],
};
} else {
return Err(PDError::CollectorPerfUnsupportedCPU.into());
}
let mut perf_list = form_events_map(base, platform_specific_counter)?;
} else {
return Err(PDError::CollectorPerfUnsupportedCPU.into());
}
}
if let Some(custom_file) = ¶ms.pmu_config {
let f = File::open(custom_file)?;
let user_provided_list: Result<Vec<NamedCtr>, serde_json::Error> =
serde_json::from_reader(&f);
match user_provided_list {
Ok(ul) => {
info!("Using custom PMU configuration provided by user.");
perf_list = ul;
}
Err(_) => {
error!("User provided PMU configuration is invalid. Aperf exiting...");
std::process::exit(1);
}
}
}
/* Write the pmu_config being used to the recorded data */
let perf_list_pathbuf = PathBuf::from(¶ms.data_dir).join("pmu_config.json");
let f = File::create(&perf_list_pathbuf)?;
serde_json::to_writer_pretty(f, &perf_list)?;
for cpu in 0..num_cpus {
for named_ctr in &perf_list {
let perf_group = Builder::new(Software::DUMMY)
.read_format(
ReadFormat::GROUP
| ReadFormat::TOTAL_TIME_ENABLED
| ReadFormat::TOTAL_TIME_RUNNING
| ReadFormat::ID,
)
.any_pid()
.one_cpu(cpu)
.build_group();
let group = match perf_group {
Err(e) => {
match e.kind() {
ErrorKind::PermissionDenied => {
warn!("Set /proc/sys/kernel/perf_event_paranoid to 0")
}
ErrorKind::NotFound => warn!("Instance does not expose Perf counters"),
_ => warn!("Unknown error when trying to use Perf API"),
}
return Err(e.into());
}
Ok(g) => g,
};
let mut cpu_group = CpuCtrGroup {
cpu: cpu as u64,
name: named_ctr.name.to_string(),
nr_ctrs: Vec::new(),
dr_ctrs: Vec::new(),
scale: named_ctr.scale,
group,
};
for nr in &named_ctr.nrs {
let nr_ctr = Ctr::new(
nr.perf_type as u64,
nr.name.to_string(),
cpu,
nr.config,
&mut cpu_group.group,
);
match nr_ctr {
Err(e) => {
if let Some(os_error) = e.downcast_ref::<std::io::Error>() {
match os_error.kind() {
ErrorKind::NotFound => {
warn!("Instance does not expose Perf counters")
}
_ => match os_error.raw_os_error().unwrap() {
libc::EMFILE => warn!(
"Too many open files. Increase limit with `ulimit -n 65536`"
),
_ => warn!("Unknown error when trying to use Perf API."),
},
}
return Err(e);
}
}
Ok(v) => cpu_group.nr_ctr_add(v),
}
}
for dr in &named_ctr.drs {
let dr_ctr = Ctr::new(
dr.perf_type as u64,
dr.name.to_string(),
cpu,
dr.config,
&mut cpu_group.group,
);
match dr_ctr {
Err(e) => {
if let Some(os_error) = e.downcast_ref::<std::io::Error>() {
match os_error.kind() {
ErrorKind::NotFound => {
warn!("Instance does not expose Perf counters")
}
_ => match os_error.raw_os_error().unwrap() {
libc::EMFILE => warn!(
"Too many open files. Increase limit with `ulimit -n 65536`"
),
_ => warn!("Unknown error when trying to use Perf API."),
},
}
return Err(e);
}
}
Ok(v) => cpu_group.dr_ctr_add(v),
}
}
cpu_groups.push(cpu_group);
}
}
for cpu_group in &mut *cpu_groups {
cpu_group.group.reset()?;
cpu_group.group.enable()?;
}
CPU_CTR_GROUPS.lock().unwrap().append(&mut cpu_groups);
Ok(())
}