-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmodel.rs
192 lines (180 loc) · 6.17 KB
/
model.rs
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
use crate::c_headers;
use crate::taskstats;
use std::mem;
use std::time::Duration;
// https://stackoverflow.com/questions/53619695/calculating-maximum-value-of-a-set-of-constant-expressions-at-compile-time
const fn const_max(a: usize, b: usize) -> usize {
[a, b][(a < b) as usize]
}
pub const TASKSTATS_SIZE: usize = const_max(
mem::size_of::<taskstats>(),
mem::size_of::<c_headers::taskstats>(),
);
/// The taskstats representation for a task.
/// This struct remaps commonly used `struct taskstats` fields for primarily:
/// * Access values with rust's primitive types
/// * Better structured organization of group of fields
/// * Support serialization
///
/// There are more (but may not much interested) fields in the original
/// `struct taskstats` and they are accessible through obtaining the original
/// struct by `TaskStats#inner()`.
#[derive(Clone, Copy, Debug)]
pub struct TaskStats {
pub(crate) inner_buf: [u8; TASKSTATS_SIZE],
/// The target task ID
pub tid: u32,
/// Staticstics related to CPU time
pub cpu: Cpu,
/// Statistics related to memory, vm
pub memory: Memory,
/// Staticstics related to I/O at syscall surface
pub io: Io,
/// Statistics related to I/O at block device level
pub blkio: BlkIo,
/// Statistics related to context switches
pub ctx_switches: ContextSwitches,
/// Statistics related to scheduling delay (delay accounting)
pub delays: Delays,
}
/// Staticstics related to CPU time
#[derive(Debug, Clone, Copy)]
pub struct Cpu {
/// User CPU time
pub utime_total: Duration,
/// System CPU time
pub stime_total: Duration,
/// Wall-clock running time
pub real_time_total: Duration,
/// Virtual running time
pub virtual_time_total: Duration,
}
/// Statistics related to memory, vm
#[derive(Debug, Clone, Copy)]
pub struct Memory {
/// Accumulated RSS usage in duration of a task, in MBytes-usecs
pub rss_total: u64,
/// Accumulated virtual memory usage in duration of a task
pub virt_total: u64,
/// Minor faults count
pub minor_faults: u64,
/// Major faults count
pub major_faults: u64,
}
/// Staticstics related to I/O at syscall surface
#[derive(Debug, Clone, Copy)]
pub struct Io {
/// Bytes read
pub read_bytes: u64,
/// Bytes written
pub write_bytes: u64,
/// Number of read syscalls
pub read_syscalls: u64,
/// Number of write syscalls
pub write_syscalls: u64,
}
/// Statistics related to I/O at block device level
#[derive(Debug, Clone, Copy)]
pub struct BlkIo {
/// Bytes read
pub read_bytes: u64,
/// Bytes written
pub write_bytes: u64,
/// Bytes of cancelled writes
pub cancelled_write_bytes: u64,
}
/// Statistics related to context switches
#[derive(Debug, Clone, Copy)]
pub struct ContextSwitches {
/// Count of voluntary context switches
pub voluntary: u64,
/// Count of non-voluntary context switches
pub non_voluntary: u64,
}
/// Statistics related to scheduling delay (delay accounting)
#[derive(Debug, Clone, Copy)]
pub struct Delays {
/// Delay waiting for cpu, while runnable
pub cpu: DelayStat,
/// Delay waiting for synchronous block I/O to complete
pub blkio: DelayStat,
/// Delay waiting for page fault I/O (swap in only)
pub swapin: DelayStat,
/// Delay waiting for memory reclaim
pub freepages: DelayStat,
}
#[derive(Debug, Clone, Copy)]
pub struct DelayStat {
/// Number of delay values recorded
pub count: u64,
/// Cumulative total delay
pub delay_total: Duration,
}
impl From<&[u8]> for TaskStats {
fn from(buf: &[u8]) -> Self {
let mut inner_buf = [0u8; TASKSTATS_SIZE];
inner_buf.copy_from_slice(&buf[..TASKSTATS_SIZE]);
let ts = unsafe { &*(inner_buf.as_ptr() as *const _ as *const taskstats) };
TaskStats {
tid: ts.ac_pid,
cpu: Cpu {
utime_total: Duration::from_micros(ts.ac_utime),
stime_total: Duration::from_micros(ts.ac_stime),
real_time_total: Duration::from_nanos(ts.cpu_run_real_total),
virtual_time_total: Duration::from_nanos(ts.cpu_run_virtual_total),
},
memory: Memory {
rss_total: ts.coremem,
virt_total: ts.virtmem,
minor_faults: ts.ac_minflt,
major_faults: ts.ac_majflt,
},
io: Io {
read_bytes: ts.read_char,
write_bytes: ts.write_char,
read_syscalls: ts.read_syscalls,
write_syscalls: ts.write_syscalls,
},
blkio: BlkIo {
read_bytes: ts.read_bytes,
write_bytes: ts.write_bytes,
cancelled_write_bytes: ts.cancelled_write_bytes,
},
ctx_switches: ContextSwitches {
voluntary: ts.nvcsw,
non_voluntary: ts.nivcsw,
},
delays: Delays {
cpu: DelayStat {
count: ts.cpu_count,
delay_total: Duration::from_nanos(ts.cpu_delay_total),
},
blkio: DelayStat {
count: ts.blkio_count,
delay_total: Duration::from_nanos(ts.blkio_delay_total),
},
swapin: DelayStat {
count: ts.swapin_count,
delay_total: Duration::from_nanos(ts.swapin_delay_total),
},
freepages: DelayStat {
count: ts.freepages_count,
delay_total: Duration::from_nanos(ts.freepages_delay_total),
},
},
inner_buf,
}
}
}
impl TaskStats {
/// Return inner representation of taskstats.
///
/// The returned value is an instance of `struct taskstats` that was
/// received from kernel.
/// `TaskStats` remaps most of its fields into rust-friendly types and
/// structure, so this inner object should be referred only when the user
/// wants to access more information than available in remapped fields.
pub fn inner(&self) -> &taskstats {
unsafe { &*(self.inner_buf.as_ptr() as *const _ as *const taskstats) }
}
}