blob: 3895aec093e8328ddc3020781c71edd6d5a2e6a0 [file] [log] [blame]
use crate::{Event, Profiler, ProfilingData, SerializationSink, StringId, TimestampKind};
use rustc_hash::FxHashMap;
use std::borrow::Cow;
use std::default::Default;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::SystemTime;
fn mk_filestem(file_name_stem: &str) -> PathBuf {
let mut path = PathBuf::new();
path.push("test-tmp");
path.push("end_to_end_serialization");
path.push(file_name_stem);
path
}
// Generate some profiling data. This is the part that would run in rustc.
fn generate_profiling_data<S: SerializationSink>(filestem: &Path) -> Vec<Event<'static>> {
let profiler = Arc::new(Profiler::<S>::new(Path::new(filestem)).unwrap());
let event_id_reserved = StringId::reserved(42);
let event_ids = &[
(
profiler.alloc_string("Generic"),
profiler.alloc_string("SomeGenericActivity"),
),
(profiler.alloc_string("Query"), event_id_reserved),
];
// This and event_ids have to match!
let mut event_ids_as_str: FxHashMap<_, _> = Default::default();
event_ids_as_str.insert(event_ids[0].0, "Generic");
event_ids_as_str.insert(event_ids[0].1, "SomeGenericActivity");
event_ids_as_str.insert(event_ids[1].0, "Query");
event_ids_as_str.insert(event_ids[1].1, "SomeQuery");
let mut expected_events = Vec::new();
let mut started_events = Vec::new();
for i in 0..10_000 {
// Allocate some invocation stacks
for _ in 0..4 {
let thread_id = (i % 3) as u64;
let (event_kind, event_id) = event_ids[i % event_ids.len()];
profiler.record_event(event_kind, event_id, thread_id, TimestampKind::Start);
started_events.push((event_kind, event_id, thread_id));
expected_events.push(Event {
event_kind: Cow::from(event_ids_as_str[&event_kind]),
label: Cow::from(event_ids_as_str[&event_id]),
additional_data: &[],
timestamp: SystemTime::UNIX_EPOCH, // We can't test this anyway,
timestamp_kind: TimestampKind::Start,
thread_id,
});
}
while let Some((event_kind, event_id, thread_id)) = started_events.pop() {
profiler.record_event(event_kind, event_id, thread_id, TimestampKind::End);
expected_events.push(Event {
event_kind: Cow::from(event_ids_as_str[&event_kind]),
label: Cow::from(event_ids_as_str[&event_id]),
additional_data: &[],
timestamp: SystemTime::UNIX_EPOCH, // We can't test this anyway,
timestamp_kind: TimestampKind::End,
thread_id,
});
}
}
// An example of allocating the string contents of an event id that has
// already been used
profiler.alloc_string_with_reserved_id(event_id_reserved, "SomeQuery");
expected_events
}
// Process some profiling data. This is the part that would run in a
// post processing tool.
fn process_profiling_data(filestem: &Path, expected_events: &[Event<'static>]) {
let profiling_data = ProfilingData::new(filestem).unwrap();
let mut count = 0;
for (actual_event, expected_event) in profiling_data.iter().zip(expected_events.iter()) {
eprintln!("{:?}", actual_event);
assert_eq!(actual_event.event_kind, expected_event.event_kind);
assert_eq!(actual_event.label, expected_event.label);
assert_eq!(actual_event.additional_data, expected_event.additional_data);
assert_eq!(actual_event.timestamp_kind, expected_event.timestamp_kind);
count += 1;
}
assert_eq!(count, expected_events.len());
}
pub fn run_end_to_end_serialization_test<S: SerializationSink>(file_name_stem: &str) {
let filestem = mk_filestem(file_name_stem);
let expected_events = generate_profiling_data::<S>(&filestem);
process_profiling_data(&filestem, &expected_events);
}