1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
//! 这只为读取CpuCycles特化,不是对[perf_event_read](https://www.man7.org/linux/man-pages/man2/perf_event_open.2.html)的完整封装
//! ⚠ 权限要求: 确保程序拥有root权限
mod ffi;
use std::{collections::HashMap, ptr, slice};
use ffi::CyclesReaderRaw;
use libc::{c_int, c_longlong as c_ll, c_void};
pub struct CyclesReader {
raw_ptr: *mut CyclesReaderRaw,
cpus: Vec<c_int>,
}
impl Drop for CyclesReader {
fn drop(&mut self) {
unsafe { ffi::destroyCyclesReader(self.raw_ptr) } // ffi里面已经drop了指针,不需要ptr::drop_in_place
self.raw_ptr = ptr::null_mut();
}
}
impl CyclesReader {
/// 创建CyclesReader
/// ```ignore
/// use cpu_cycles_reader::CyclesReader;
/// let reader = CyclesReader::new(&[0, 1, 2, 3]);
/// ```
pub fn new(cpus: &[c_int]) -> Result<Self, &'static str> {
let cpus = cpus.to_vec();
let cpus_ptr = cpus.as_ptr();
let raw_ptr = unsafe { ffi::createCyclesReader(cpus_ptr, cpus.len()) };
if raw_ptr.is_null() {
return Err("Failed to create CyclesReader");
}
Ok(Self { raw_ptr, cpus })
}
/// 开启Cycles监视
/// ```ignore
/// use cpu_cycles_reader::CyclesReader;
/// let reader = CyclesReader::new(&[0, 1, 2, 3]).unwrap();
/// reader.enable();
/// ```
pub fn enable(&self) {
unsafe {
ffi::enableCyclesReader(self.raw_ptr);
}
}
/// 关闭Cycles监视
/// ```ignore
/// use cpu_cycles_reader::CyclesReader;
/// let reader = CyclesReader::new(&[0, 1, 2, 3]).unwrap();
/// reader.disable();
/// ```
pub fn disable(&self) {
unsafe {
ffi::disableCyclesReader(self.raw_ptr);
}
}
/// 读取从开启到现在的Cycles数
/// 按照构造函数cpu参数顺序返回
pub fn read(&self) -> Result<HashMap<c_int, c_ll>, &'static str> {
let raw = unsafe { ffi::readCyclesReader(self.raw_ptr) };
if raw.is_null() {
return Err("CyclesReader failed to read");
}
let slice = unsafe { slice::from_raw_parts(raw, (*self.raw_ptr).size) };
let map = self.cpus.iter().zip(slice).map(|(c, d)| (*c, *d)).collect(); // copied here
// 释放ffi malloc的数组
unsafe { libc::free(raw as *mut c_void) }
Ok(map)
}
}