]> git.proxmox.com Git - rustc.git/blame - vendor/measureme/src/profiling_data.rs
New upstream version 1.40.0+dfsg1
[rustc.git] / vendor / measureme / src / profiling_data.rs
CommitLineData
48663c56 1use crate::event::Event;
e74abb32 2use crate::file_header::FILE_HEADER_SIZE;
48663c56
XL
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");
e74abb32
XL
20 let index_data =
21 fs::read(paths.string_index_file).expect("couldn't read string_index file");
48663c56
XL
22 let event_data = fs::read(paths.events_file).expect("couldn't read events file");
23
24 let string_table = StringTable::new(string_data, index_data)?;
25
26 Ok(ProfilingData {
27 string_table,
28 event_data,
29 })
30 }
31
32 pub fn iter(&self) -> impl Iterator<Item = Event<'_>> {
33 ProfilerEventIterator::new(&self)
34 }
35
36 pub fn iter_matching_events(&self) -> impl Iterator<Item = MatchingEvent<'_>> {
37 MatchingEventsIterator::new(ProfilerEventIterator::new(&self))
38 }
39}
40
41struct ProfilerEventIterator<'a> {
42 data: &'a ProfilingData,
43 curr_event_idx: usize,
44}
45
46impl<'a> ProfilerEventIterator<'a> {
47 pub fn new(data: &'a ProfilingData) -> ProfilerEventIterator<'a> {
48 ProfilerEventIterator {
49 data,
50 curr_event_idx: 0,
51 }
52 }
53}
54
55impl<'a> Iterator for ProfilerEventIterator<'a> {
56 type Item = Event<'a>;
57
58 fn next(&mut self) -> Option<Event<'a>> {
e74abb32 59 let event_start_addr = FILE_HEADER_SIZE + self.curr_event_idx * mem::size_of::<RawEvent>();
48663c56
XL
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,
e74abb32 73 std::mem::size_of::<RawEvent>(),
48663c56
XL
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();
e74abb32 124 self.thread_stacks.append(&mut vec![vec![]; growth_size])
48663c56
XL
125 }
126
127 self.thread_stacks[thread_id].push(event);
e74abb32 128 }
48663c56
XL
129 TimestampKind::Instant => {
130 return Some(MatchingEvent::Instant(event));
e74abb32 131 }
48663c56
XL
132 TimestampKind::End => {
133 let thread_id = event.thread_id as usize;
e74abb32
XL
134 let previous_event = self.thread_stacks[thread_id]
135 .pop()
136 .expect("no previous event");
137 if previous_event.event_kind != event.event_kind
138 || previous_event.label != event.label
139 {
140 panic!(
141 "the event with label: \"{}\" went out of scope of the parent \
142 event with label: \"{}\"",
143 previous_event.label, event.label
144 );
48663c56
XL
145 }
146
147 return Some(MatchingEvent::StartStop(previous_event, event));
148 }
149 }
150 }
151
152 None
153 }
154}