@@ -18,12 +18,16 @@ fn mk_filestem(file_name_stem: &str) -> PathBuf {
1818}
1919
2020// Generate some profiling data. This is the part that would run in rustc.
21- fn generate_profiling_data < S : SerializationSink > ( filestem : & Path ) -> Vec < Event < ' static > > {
21+ fn generate_profiling_data < S : SerializationSink > (
22+ filestem : & Path ,
23+ num_stacks : usize ,
24+ num_threads : usize ,
25+ ) -> Vec < Event < ' static > > {
2226 let profiler = Arc :: new ( Profiler :: < S > :: new ( Path :: new ( filestem) ) . unwrap ( ) ) ;
2327
2428 let event_id_reserved = StringId :: reserved ( 42 ) ;
2529
26- let event_ids = & [
30+ let event_ids = vec ! [
2731 (
2832 profiler. alloc_string( "Generic" ) ,
2933 profiler. alloc_string( "SomeGenericActivity" ) ,
@@ -38,20 +42,33 @@ fn generate_profiling_data<S: SerializationSink>(filestem: &Path) -> Vec<Event<'
3842 event_ids_as_str. insert ( event_ids[ 1 ] . 0 , "Query" ) ;
3943 event_ids_as_str. insert ( event_ids[ 1 ] . 1 , "SomeQuery" ) ;
4044
41- let mut expected_events = Vec :: new ( ) ;
45+ let threads: Vec < _ > = ( 0 .. num_threads) . map ( |thread_id| {
46+ let event_ids = event_ids. clone ( ) ;
47+ let profiler = profiler. clone ( ) ;
48+ let event_ids_as_str = event_ids_as_str. clone ( ) ;
4249
43- for i in 0 .. 10_000 {
44- // Allocate some invocation stacks
50+ std :: thread :: spawn ( move || {
51+ let mut expected_events = Vec :: new ( ) ;
4552
46- pseudo_invocation (
47- & profiler,
48- i,
49- 4 ,
50- event_ids,
51- & event_ids_as_str,
52- & mut expected_events,
53- ) ;
54- }
53+ for i in 0 ..num_stacks {
54+ // Allocate some invocation stacks
55+
56+ pseudo_invocation (
57+ & profiler,
58+ i,
59+ thread_id as u64 ,
60+ 4 ,
61+ & event_ids[ ..] ,
62+ & event_ids_as_str,
63+ & mut expected_events,
64+ ) ;
65+ }
66+
67+ expected_events
68+ } )
69+ } ) . collect ( ) ;
70+
71+ let expected_events: Vec < _ > = threads. into_iter ( ) . flat_map ( |t| t. join ( ) . unwrap ( ) ) . collect ( ) ;
5572
5673 // An example of allocating the string contents of an event id that has
5774 // already been used
@@ -84,34 +101,65 @@ fn check_profiling_data(
84101) {
85102 let mut count = 0 ;
86103
104+ // This assertion makes sure that the ExactSizeIterator impl works as expected.
87105 assert_eq ! (
88106 ( num_expected_events, Some ( num_expected_events) ) ,
89107 actual_events. size_hint( )
90108 ) ;
91109
92- for ( actual_event, expected_event) in actual_events. zip ( expected_events) {
93- assert_eq ! ( actual_event. event_kind, expected_event. event_kind) ;
94- assert_eq ! ( actual_event. label, expected_event. label) ;
95- assert_eq ! ( actual_event. additional_data, expected_event. additional_data) ;
96- assert_eq ! (
97- actual_event. timestamp. is_instant( ) ,
98- expected_event. timestamp. is_instant( )
99- ) ;
110+ let actual_events_per_thread = collect_events_per_thread ( actual_events) ;
111+ let expected_events_per_thread = collect_events_per_thread ( expected_events) ;
112+
113+ let thread_ids: Vec < _ > = actual_events_per_thread. keys ( ) . collect ( ) ;
114+ assert_eq ! ( thread_ids, expected_events_per_thread. keys( ) . collect:: <Vec <_>>( ) ) ;
100115
101- count += 1 ;
116+ for thread_id in thread_ids {
117+ let actual_events = & actual_events_per_thread[ thread_id] ;
118+ let expected_events = & expected_events_per_thread[ thread_id] ;
119+
120+ assert_eq ! ( actual_events. len( ) , expected_events. len( ) ) ;
121+
122+ for ( actual_event, expected_event) in actual_events. iter ( ) . zip ( expected_events. iter ( ) ) {
123+ assert_eq ! ( actual_event. event_kind, expected_event. event_kind) ;
124+ assert_eq ! ( actual_event. label, expected_event. label) ;
125+ assert_eq ! ( actual_event. additional_data, expected_event. additional_data) ;
126+ assert_eq ! (
127+ actual_event. timestamp. is_instant( ) ,
128+ expected_event. timestamp. is_instant( )
129+ ) ;
130+
131+ count += 1 ;
132+ }
102133 }
134+
103135 assert_eq ! ( count, num_expected_events) ;
104136}
105137
106- pub fn run_end_to_end_serialization_test < S : SerializationSink > ( file_name_stem : & str ) {
138+ fn collect_events_per_thread < ' a > ( events : & mut dyn Iterator < Item = Event < ' a > > ) -> FxHashMap < u64 , Vec < Event < ' a > > > {
139+ let mut per_thread: FxHashMap < _ , _ > = Default :: default ( ) ;
140+
141+ for event in events {
142+ per_thread. entry ( event. thread_id ) . or_insert ( Vec :: new ( ) ) . push ( event) ;
143+ }
144+
145+ per_thread
146+ }
147+
148+ pub fn run_serialization_bench < S : SerializationSink > ( file_name_stem : & str , num_events : usize , num_threads : usize ) {
107149 let filestem = mk_filestem ( file_name_stem) ;
108- let expected_events = generate_profiling_data :: < S > ( & filestem) ;
150+ generate_profiling_data :: < S > ( & filestem, num_events, num_threads) ;
151+ }
152+
153+ pub fn run_end_to_end_serialization_test < S : SerializationSink > ( file_name_stem : & str , num_threads : usize ) {
154+ let filestem = mk_filestem ( file_name_stem) ;
155+ let expected_events = generate_profiling_data :: < S > ( & filestem, 10_000 , num_threads) ;
109156 process_profiling_data ( & filestem, & expected_events) ;
110157}
111158
112159fn pseudo_invocation < S : SerializationSink > (
113160 profiler : & Profiler < S > ,
114161 random : usize ,
162+ thread_id : u64 ,
115163 recursions_left : usize ,
116164 event_ids : & [ ( StringId , StringId ) ] ,
117165 event_ids_as_str : & FxHashMap < StringId , & ' static str > ,
@@ -121,15 +169,14 @@ fn pseudo_invocation<S: SerializationSink>(
121169 return ;
122170 }
123171
124- let thread_id = ( random % 3 ) as u64 ;
125-
126172 let ( event_kind, event_id) = event_ids[ random % event_ids. len ( ) ] ;
127173
128174 let _prof_guard = profiler. start_recording_interval_event ( event_kind, event_id, thread_id) ;
129175
130176 pseudo_invocation (
131177 profiler,
132178 random,
179+ thread_id,
133180 recursions_left - 1 ,
134181 event_ids,
135182 event_ids_as_str,
0 commit comments