shadow_rs/core/
sim_stats.rs
1use std::cell::RefCell;
2use std::sync::Mutex;
3
4use anyhow::Context;
5use serde::Serialize;
6
7use crate::utility::counter::Counter;
8
9#[derive(Debug)]
11pub struct LocalSimStats {
12 pub alloc_counts: RefCell<Counter>,
13 pub dealloc_counts: RefCell<Counter>,
14 pub syscall_counts: RefCell<Counter>,
15}
16
17impl LocalSimStats {
18 pub fn new() -> Self {
19 Self {
20 alloc_counts: RefCell::new(Counter::new()),
21 dealloc_counts: RefCell::new(Counter::new()),
22 syscall_counts: RefCell::new(Counter::new()),
23 }
24 }
25}
26
27impl Default for LocalSimStats {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33#[derive(Debug)]
35pub struct SharedSimStats {
36 pub alloc_counts: Mutex<Counter>,
37 pub dealloc_counts: Mutex<Counter>,
38 pub syscall_counts: Mutex<Counter>,
39}
40
41impl SharedSimStats {
42 pub fn new() -> Self {
43 Self {
44 alloc_counts: Mutex::new(Counter::new()),
45 dealloc_counts: Mutex::new(Counter::new()),
46 syscall_counts: Mutex::new(Counter::new()),
47 }
48 }
49
50 pub fn add_from_local_stats(&self, local: &LocalSimStats) {
52 let mut shared_alloc_counts = self.alloc_counts.lock().unwrap();
53 let mut shared_dealloc_counts = self.dealloc_counts.lock().unwrap();
54 let mut shared_syscall_counts = self.syscall_counts.lock().unwrap();
55
56 let mut local_alloc_counts = local.alloc_counts.borrow_mut();
57 let mut local_dealloc_counts = local.dealloc_counts.borrow_mut();
58 let mut local_syscall_counts = local.syscall_counts.borrow_mut();
59
60 shared_alloc_counts.add_counter(&local_alloc_counts);
61 shared_dealloc_counts.add_counter(&local_dealloc_counts);
62 shared_syscall_counts.add_counter(&local_syscall_counts);
63
64 *local_alloc_counts = Counter::new();
65 *local_dealloc_counts = Counter::new();
66 *local_syscall_counts = Counter::new();
67 }
68}
69
70impl Default for SharedSimStats {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76#[derive(Serialize, Clone, Debug)]
78struct SimStatsForOutput {
79 pub objects: ObjectStatsForOutput,
80 pub syscalls: Counter,
81}
82
83#[derive(Serialize, Clone, Debug)]
84struct ObjectStatsForOutput {
85 pub alloc_counts: Counter,
86 pub dealloc_counts: Counter,
87}
88
89impl SimStatsForOutput {
90 pub fn new(stats: &SharedSimStats) -> Self {
93 Self {
94 objects: ObjectStatsForOutput {
95 alloc_counts: std::mem::replace(
96 &mut stats.alloc_counts.lock().unwrap(),
97 Counter::new(),
98 ),
99 dealloc_counts: std::mem::replace(
100 &mut stats.dealloc_counts.lock().unwrap(),
101 Counter::new(),
102 ),
103 },
104 syscalls: std::mem::replace(&mut stats.syscall_counts.lock().unwrap(), Counter::new()),
105 }
106 }
107}
108
109pub fn write_stats_to_file(
111 filename: &std::path::Path,
112 stats: &SharedSimStats,
113) -> anyhow::Result<()> {
114 let stats = SimStatsForOutput::new(stats);
115
116 let file = std::fs::File::create(filename)
117 .with_context(|| format!("Failed to create file '{}'", filename.display()))?;
118
119 serde_json::to_writer_pretty(file, &stats).with_context(|| {
120 format!(
121 "Failed to write stats json to file '{}'",
122 filename.display()
123 )
124 })?;
125
126 Ok(())
127}