]> git.proxmox.com Git - rustc.git/blame - vendor/measureme/src/profiling_data.rs
New upstream version 1.36.0+dfsg1
[rustc.git] / vendor / measureme / src / profiling_data.rs
CommitLineData
48663c56
XL
1use crate::file_header::FILE_HEADER_SIZE;
2use crate::event::Event;
3use crate::{ProfilerFiles, RawEvent, StringTable, TimestampKind};
4use std::error::Error;
5use std::fs;
6use std::mem;
7use std::path::Path;
8use std::time::{Duration, SystemTime};
9
10pub struct ProfilingData {
11 event_data: Vec<u8>,
12 string_table: StringTable,
13}
14
15impl ProfilingData {
16 pub fn new(path_stem: &Path) -> Result<ProfilingData, Box<dyn Error>> {
17 let paths = ProfilerFiles::new(path_stem);
18
19 let string_data = fs::read(paths.string_data_file).expect("couldn't read string_data file");
20 let index_data = fs::read(paths.string_index_file).expect("couldn't read string_index file");
21 let event_data = fs::read(paths.events_file).expect("couldn't read events file");
22
23 let string_table = StringTable::new(string_data, index_data)?;
24
25 Ok(ProfilingData {
26 string_table,
27 event_data,
28 })
29 }
30
31 pub fn iter(&self) -> impl Iterator<Item = Event<'_>> {
32 ProfilerEventIterator::new(&self)
33 }
34
35 pub fn iter_matching_events(&self) -> impl Iterator<Item = MatchingEvent<'_>> {
36 MatchingEventsIterator::new(ProfilerEventIterator::new(&self))
37 }
38}
39
40struct ProfilerEventIterator<'a> {
41 data: &'a ProfilingData,
42 curr_event_idx: usize,
43}
44
45impl<'a> ProfilerEventIterator<'a> {
46 pub fn new(data: &'a ProfilingData) -> ProfilerEventIterator<'a> {
47 ProfilerEventIterator {
48 data,
49 curr_event_idx: 0,
50 }
51 }
52}
53
54impl<'a> Iterator for ProfilerEventIterator<'a> {
55 type Item = Event<'a>;
56
57 fn next(&mut self) -> Option<Event<'a>> {
58 let event_start_addr = FILE_HEADER_SIZE +
59 self.curr_event_idx * mem::size_of::<RawEvent>();
60 let event_end_addr = event_start_addr + mem::size_of::<RawEvent>();
61 if event_end_addr > self.data.event_data.len() {
62 return None;
63 }
64
65 self.curr_event_idx += 1;
66
67 let raw_event_bytes = &self.data.event_data[event_start_addr..event_end_addr];
68
69 let mut raw_event = RawEvent::default();
70 unsafe {
71 let raw_event = std::slice::from_raw_parts_mut(
72 &mut raw_event as *mut RawEvent as *mut u8,
73 std::mem::size_of::<RawEvent>()
74 );
75 raw_event.copy_from_slice(raw_event_bytes);
76 };
77
78 let string_table = &self.data.string_table;
79
80 let mut timestamp = SystemTime::UNIX_EPOCH;
81 timestamp += Duration::from_nanos(raw_event.timestamp.nanos());
82
83 Some(Event {
84 event_kind: string_table.get(raw_event.event_kind).to_string(),
85 label: string_table.get(raw_event.id).to_string(),
86 additional_data: &[],
87 timestamp: timestamp,
88 timestamp_kind: raw_event.timestamp.kind(),
89 thread_id: raw_event.thread_id,
90 })
91 }
92}
93
94#[derive(Clone, Debug, PartialEq, Eq, Hash)]
95pub enum MatchingEvent<'a> {
96 StartStop(Event<'a>, Event<'a>),
97 Instant(Event<'a>),
98}
99
100struct MatchingEventsIterator<'a> {
101 events: ProfilerEventIterator<'a>,
102 thread_stacks: Vec<Vec<Event<'a>>>,
103}
104
105impl<'a> MatchingEventsIterator<'a> {
106 pub fn new(events: ProfilerEventIterator<'a>) -> MatchingEventsIterator<'a> {
107 MatchingEventsIterator {
108 events,
109 thread_stacks: vec![],
110 }
111 }
112}
113
114impl<'a> Iterator for MatchingEventsIterator<'a> {
115 type Item = MatchingEvent<'a>;
116
117 fn next(&mut self) -> Option<MatchingEvent<'a>> {
118 while let Some(event) = self.events.next() {
119 match event.timestamp_kind {
120 TimestampKind::Start => {
121 let thread_id = event.thread_id as usize;
122 if thread_id >= self.thread_stacks.len() {
123 let growth_size = (thread_id + 1) - self.thread_stacks.len();
124 self.thread_stacks.append(
125 &mut vec![vec![]; growth_size]
126 )
127 }
128
129 self.thread_stacks[thread_id].push(event);
130 },
131 TimestampKind::Instant => {
132 return Some(MatchingEvent::Instant(event));
133 },
134 TimestampKind::End => {
135 let thread_id = event.thread_id as usize;
136 let previous_event = self.thread_stacks[thread_id].pop().expect("no previous event");
137 if previous_event.event_kind != event.event_kind ||
138 previous_event.label != event.label {
139 panic!("previous event on thread wasn't the start event");
140 }
141
142 return Some(MatchingEvent::StartStop(previous_event, event));
143 }
144 }
145 }
146
147 None
148 }
149}