@@ -97,6 +97,7 @@ use std::time::{Duration, Instant};
97
97
pub use measureme:: EventId ;
98
98
use measureme:: { EventIdBuilder , Profiler , SerializableString , StringId } ;
99
99
use parking_lot:: RwLock ;
100
+ use serde_json:: json;
100
101
use smallvec:: SmallVec ;
101
102
102
103
bitflags:: bitflags! {
@@ -145,6 +146,15 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
145
146
/// Something that uniquely identifies a query invocation.
146
147
pub struct QueryInvocationId ( pub u32 ) ;
147
148
149
+ /// Which format to use for `-Z time-passes`
150
+ #[ derive( Clone , Copy , PartialEq , Hash , Debug ) ]
151
+ pub enum TimePassesFormat {
152
+ /// Emit human readable text
153
+ Text ,
154
+ /// Emit structured JSON
155
+ Json ,
156
+ }
157
+
148
158
/// A reference to the SelfProfiler. It can be cloned and sent across thread
149
159
/// boundaries at will.
150
160
#[ derive( Clone ) ]
@@ -158,14 +168,14 @@ pub struct SelfProfilerRef {
158
168
// actually enabled.
159
169
event_filter_mask : EventFilter ,
160
170
161
- // Print verbose generic activities to stderr?
162
- print_verbose_generic_activities : bool ,
171
+ // Print verbose generic activities to stderr.
172
+ print_verbose_generic_activities : Option < TimePassesFormat > ,
163
173
}
164
174
165
175
impl SelfProfilerRef {
166
176
pub fn new (
167
177
profiler : Option < Arc < SelfProfiler > > ,
168
- print_verbose_generic_activities : bool ,
178
+ print_verbose_generic_activities : Option < TimePassesFormat > ,
169
179
) -> SelfProfilerRef {
170
180
// If there is no SelfProfiler then the filter mask is set to NONE,
171
181
// ensuring that nothing ever tries to actually access it.
@@ -207,9 +217,10 @@ impl SelfProfilerRef {
207
217
/// a measureme event, "verbose" generic activities also print a timing entry to
208
218
/// stderr if the compiler is invoked with -Ztime-passes.
209
219
pub fn verbose_generic_activity ( & self , event_label : & ' static str ) -> VerboseTimingGuard < ' _ > {
210
- let message = self . print_verbose_generic_activities . then ( || event_label. to_owned ( ) ) ;
220
+ let message_and_format =
221
+ self . print_verbose_generic_activities . map ( |format| ( event_label. to_owned ( ) , format) ) ;
211
222
212
- VerboseTimingGuard :: start ( message , self . generic_activity ( event_label) )
223
+ VerboseTimingGuard :: start ( message_and_format , self . generic_activity ( event_label) )
213
224
}
214
225
215
226
/// Like `verbose_generic_activity`, but with an extra arg.
@@ -221,11 +232,14 @@ impl SelfProfilerRef {
221
232
where
222
233
A : Borrow < str > + Into < String > ,
223
234
{
224
- let message = self
235
+ let message_and_format = self
225
236
. print_verbose_generic_activities
226
- . then ( || format ! ( "{}({})" , event_label, event_arg. borrow( ) ) ) ;
237
+ . map ( |format| ( format ! ( "{}({})" , event_label, event_arg. borrow( ) ) , format ) ) ;
227
238
228
- VerboseTimingGuard :: start ( message, self . generic_activity_with_arg ( event_label, event_arg) )
239
+ VerboseTimingGuard :: start (
240
+ message_and_format,
241
+ self . generic_activity_with_arg ( event_label, event_arg) ,
242
+ )
229
243
}
230
244
231
245
/// Start profiling a generic activity. Profiling continues until the
@@ -703,17 +717,32 @@ impl<'a> TimingGuard<'a> {
703
717
}
704
718
}
705
719
720
+ struct VerboseInfo {
721
+ start_time : Instant ,
722
+ start_rss : Option < usize > ,
723
+ message : String ,
724
+ format : TimePassesFormat ,
725
+ }
726
+
706
727
#[ must_use]
707
728
pub struct VerboseTimingGuard < ' a > {
708
- start_and_message : Option < ( Instant , Option < usize > , String ) > ,
729
+ info : Option < VerboseInfo > ,
709
730
_guard : TimingGuard < ' a > ,
710
731
}
711
732
712
733
impl < ' a > VerboseTimingGuard < ' a > {
713
- pub fn start ( message : Option < String > , _guard : TimingGuard < ' a > ) -> Self {
734
+ pub fn start (
735
+ message_and_format : Option < ( String , TimePassesFormat ) > ,
736
+ _guard : TimingGuard < ' a > ,
737
+ ) -> Self {
714
738
VerboseTimingGuard {
715
739
_guard,
716
- start_and_message : message. map ( |msg| ( Instant :: now ( ) , get_resident_set_size ( ) , msg) ) ,
740
+ info : message_and_format. map ( |( message, format) | VerboseInfo {
741
+ start_time : Instant :: now ( ) ,
742
+ start_rss : get_resident_set_size ( ) ,
743
+ message,
744
+ format,
745
+ } ) ,
717
746
}
718
747
}
719
748
@@ -726,10 +755,10 @@ impl<'a> VerboseTimingGuard<'a> {
726
755
727
756
impl Drop for VerboseTimingGuard < ' _ > {
728
757
fn drop ( & mut self ) {
729
- if let Some ( ( start_time , start_rss , ref message ) ) = self . start_and_message {
758
+ if let Some ( info ) = & self . info {
730
759
let end_rss = get_resident_set_size ( ) ;
731
- let dur = start_time. elapsed ( ) ;
732
- print_time_passes_entry ( message, dur, start_rss, end_rss) ;
760
+ let dur = info . start_time . elapsed ( ) ;
761
+ print_time_passes_entry ( & info . message , dur, info . start_rss , end_rss, info . format ) ;
733
762
}
734
763
}
735
764
}
@@ -739,7 +768,22 @@ pub fn print_time_passes_entry(
739
768
dur : Duration ,
740
769
start_rss : Option < usize > ,
741
770
end_rss : Option < usize > ,
771
+ format : TimePassesFormat ,
742
772
) {
773
+ match format {
774
+ TimePassesFormat :: Json => {
775
+ let json = json ! ( {
776
+ "pass" : what,
777
+ "time" : dur. as_secs_f64( ) ,
778
+ "rss_start" : start_rss,
779
+ "rss_end" : end_rss,
780
+ } ) ;
781
+ eprintln ! ( "time: {}" , json. to_string( ) ) ;
782
+ return ;
783
+ }
784
+ TimePassesFormat :: Text => ( ) ,
785
+ }
786
+
743
787
// Print the pass if its duration is greater than 5 ms, or it changed the
744
788
// measured RSS.
745
789
let is_notable = || {
0 commit comments