use super::{EventListener, PluginEvents};
#[derive(Clone)]
pub struct CacheTrasher {
cache_lines: Vec<CacheLine>,
seed: u64, }
impl Default for CacheTrasher {
fn default() -> Self {
Self::new(1024 * 1024 * 32) }
}
impl CacheTrasher {
#[allow(unused_qualifications)]
pub fn new(bytes: usize) -> Self {
let n = bytes / std::mem::size_of::<CacheLine>();
let cache_lines = vec![CacheLine::default(); n];
Self {
cache_lines,
seed: 0,
}
}
fn lcg_rand(&mut self) -> usize {
const A: u64 = 1664525;
const C: u64 = 1013904223;
self.seed = A.wrapping_mul(self.seed).wrapping_add(C);
(self.seed % (self.cache_lines.len() as u64)) as usize
}
fn issue_read(&mut self) {
let num_reads = self.cache_lines.len();
for _ in 0..num_reads {
let idx = self.lcg_rand();
unsafe { std::ptr::read_volatile(&self.cache_lines[idx].0[0]) }; }
}
}
#[repr(C)]
#[repr(align(64))]
#[derive(Default, Clone, Copy)]
struct CacheLine([u16; 32]);
impl EventListener for CacheTrasher {
fn as_any(&mut self) -> &mut dyn std::any::Any {
self
}
fn name(&self) -> &'static str {
"cache_trasher"
}
fn on_event(&mut self, event: PluginEvents) {
if let PluginEvents::BenchStart { bench_id: _ } = event {
self.issue_read();
}
}
}