1use alloc::vec::Vec;
2use hashbrown::HashMap;
3pub struct Profiler {
4 backedges: HashMap<(usize, usize), u32>,
5 hot_spots: Vec<HotSpot>,
6}
7
8#[derive(Debug, Clone)]
9pub struct HotSpot {
10 pub function_idx: usize,
11 pub start_ip: usize,
12 pub iterations: u32,
13}
14
15impl Profiler {
16 pub fn new() -> Self {
17 Self {
18 backedges: HashMap::new(),
19 hot_spots: Vec::new(),
20 }
21 }
22
23 pub fn record_backedge(&mut self, func_idx: usize, ip: usize) -> u32 {
24 let count = self
25 .backedges
26 .entry((func_idx, ip))
27 .and_modify(|c| *c += 1)
28 .or_insert(1);
29 *count
30 }
31
32 pub fn is_hot(&self, func_idx: usize, ip: usize, threshold: u32) -> bool {
33 self.backedges
34 .get(&(func_idx, ip))
35 .map(|&count| count >= threshold)
36 .unwrap_or(false)
37 }
38
39 pub fn get_count(&self, func_idx: usize, ip: usize) -> u32 {
40 self.backedges.get(&(func_idx, ip)).copied().unwrap_or(0)
41 }
42
43 pub fn mark_hot(&mut self, func_idx: usize, ip: usize) {
44 let iterations = self.get_count(func_idx, ip);
45 self.hot_spots.push(HotSpot {
46 function_idx: func_idx,
47 start_ip: ip,
48 iterations,
49 });
50 }
51
52 pub fn hot_spots(&self) -> &[HotSpot] {
53 &self.hot_spots
54 }
55
56 pub fn reset(&mut self) {
57 self.backedges.clear();
58 self.hot_spots.clear();
59 }
60}
61
62impl Default for Profiler {
63 fn default() -> Self {
64 Self::new()
65 }
66}