@@ -54,6 +54,14 @@ enum Commands {
5454 #[ arg( long, default_value = "5" ) ]
5555 stack_depth : usize ,
5656 } ,
57+ /// Print the total duration (in seconds) of the JFR recording. Used in the integration tests.
58+ Duration {
59+ /// JFR file to read from
60+ jfr_file : OsString ,
61+ /// If true, unzip first
62+ #[ arg( long) ]
63+ zip : bool ,
64+ } ,
5765}
5866
5967#[ derive( Copy , Clone , Debug , PartialEq , Eq , PartialOrd , Ord ) ]
@@ -78,6 +86,24 @@ fn extract_async_profiler_jfr_from_zip(file: File) -> anyhow::Result<Option<Vec<
7886 Ok ( None )
7987}
8088
89+ // doing this as a macro because functions are not higher-order enough
90+ // extract events from $jfr_file, $zip decides if it's a zip, then run $f($FILE, input)
91+ macro_rules! extract_events_from_path {
92+ ( $jfr_file: expr, $zip: expr, $f: expr, $input: expr) => { {
93+ let mut jfr_file = std:: fs:: File :: open( $jfr_file) ?;
94+ match $zip {
95+ false => $f( & mut jfr_file, $input) ,
96+ true => {
97+ if let Some ( data) = extract_async_profiler_jfr_from_zip( jfr_file) ? {
98+ $f( & mut Cursor :: new( & data) , $input)
99+ } else {
100+ anyhow:: bail!( "no async_profiler_dump_0.jfr file found" ) ;
101+ }
102+ }
103+ }
104+ } } ;
105+ }
106+
81107fn main ( ) -> anyhow:: Result < ( ) > {
82108 let cli = Cli :: parse ( ) ;
83109 tracing_subscriber:: fmt:: init ( ) ;
@@ -89,21 +115,11 @@ fn main() -> anyhow::Result<()> {
89115 zip,
90116 include_non_pollcatch,
91117 } => {
92- let mut jfr_file = std:: fs:: File :: open ( jfr_file) ?;
93118 let config = LongPollConfig {
94119 min_length,
95120 include_non_pollcatch,
96121 } ;
97- let samples = match zip {
98- false => jfr_samples ( & mut jfr_file, & config) ?,
99- true => {
100- if let Some ( data) = extract_async_profiler_jfr_from_zip ( jfr_file) ? {
101- jfr_samples ( & mut Cursor :: new ( & data) , & config) ?
102- } else {
103- anyhow:: bail!( "no async_profiler_dump_0.jfr file found" ) ;
104- }
105- }
106- } ;
122+ let samples = extract_events_from_path ! ( jfr_file, zip, jfr_samples, & config) ?;
107123 print_samples ( & mut io:: stdout ( ) , samples, stack_depth) . ok ( ) ;
108124 Ok ( ( ) )
109125 }
@@ -113,20 +129,15 @@ fn main() -> anyhow::Result<()> {
113129 zip,
114130 stack_depth,
115131 } => {
116- let mut jfr_file = std:: fs:: File :: open ( jfr_file) ?;
117- let events = match zip {
118- false => jfr_native_mem_events ( & mut jfr_file, & type_) ?,
119- true => {
120- if let Some ( data) = extract_async_profiler_jfr_from_zip ( jfr_file) ? {
121- jfr_native_mem_events ( & mut Cursor :: new ( & data) , & type_) ?
122- } else {
123- anyhow:: bail!( "no async_profiler_dump_0.jfr file found" ) ;
124- }
125- }
126- } ;
132+ let events = extract_events_from_path ! ( jfr_file, zip, jfr_native_mem_events, & type_) ?;
127133 print_native_mem_events ( & mut io:: stdout ( ) , events, & type_, stack_depth) . ok ( ) ;
128134 Ok ( ( ) )
129135 }
136+ Commands :: Duration { jfr_file, zip } => {
137+ let duration = extract_events_from_path ! ( jfr_file, zip, jfr_duration, ( ) ) ?;
138+ println ! ( "{}" , duration. as_secs_f64( ) ) ;
139+ Ok ( ( ) )
140+ }
130141 }
131142}
132143
@@ -659,6 +670,19 @@ where
659670 Ok ( samples)
660671}
661672
673+ fn jfr_duration < T > ( reader : & mut T , _config : ( ) ) -> anyhow:: Result < Duration >
674+ where
675+ T : Read + Seek ,
676+ {
677+ let mut jfr_reader = JfrReader :: new ( reader) ;
678+
679+ let total_nanos = jfr_reader
680+ . chunks ( )
681+ . map ( |i| i. map ( |i| i. 1 . header . duration_nanos ) )
682+ . sum :: < Result < i64 , _ > > ( ) ?;
683+ Ok ( Duration :: from_nanos ( total_nanos as u64 ) )
684+ }
685+
662686#[ derive( Debug ) ]
663687struct NativeMemEvent {
664688 start_time : Duration ,
@@ -934,6 +958,9 @@ mod test {
934958 }
935959 print_samples ( & mut to, samples, 4 ) . unwrap ( ) ;
936960 assert_eq ! ( String :: from_utf8( to) . unwrap( ) , result) ;
961+
962+ let duration = crate :: jfr_duration ( & mut io:: Cursor :: new ( jfr) , ( ) ) . unwrap ( ) ;
963+ assert_eq ! ( duration. as_nanos( ) , 15003104000 ) ;
937964 }
938965
939966 #[ test]
0 commit comments