@@ -9,6 +9,7 @@ use std::{
9
9
} ;
10
10
11
11
use once_cell:: sync:: Lazy ;
12
+ use itertools:: Itertools ;
12
13
13
14
/// Set profiling filter. It specifies descriptions allowed to profile.
14
15
/// This is helpful when call stack has too many nested profiling scopes.
@@ -179,8 +180,9 @@ impl Drop for Profiler {
179
180
stack. messages . push ( Message { level, duration, message } ) ;
180
181
if level == 0 {
181
182
let stdout = stderr ( ) ;
182
- if duration >= stack. filter_data . longer_than {
183
- print ( 0 , & stack. messages , & mut stdout. lock ( ) ) ;
183
+ let longer_than = stack. filter_data . longer_than ;
184
+ if duration >= longer_than {
185
+ print ( 0 , & stack. messages , & mut stdout. lock ( ) , longer_than) ;
184
186
}
185
187
stack. messages . clear ( ) ;
186
188
}
@@ -191,20 +193,37 @@ impl Drop for Profiler {
191
193
}
192
194
}
193
195
194
- fn print ( lvl : usize , msgs : & [ Message ] , out : & mut impl Write ) {
196
+ fn print ( lvl : usize , msgs : & [ Message ] , out : & mut impl Write , longer_than : Duration ) {
195
197
let mut last = 0 ;
196
198
let indent = repeat ( " " ) . take ( lvl + 1 ) . collect :: < String > ( ) ;
197
- for ( i, & Message { level : l, duration : dur, message : ref msg } ) in msgs. iter ( ) . enumerate ( ) {
198
- if l != lvl {
199
+ // We output hierarchy for long calls, but sum up all short calls
200
+ let mut short = Vec :: new ( ) ;
201
+ for ( i, & Message { level, duration, message : ref msg } ) in msgs. iter ( ) . enumerate ( ) {
202
+ if level != lvl {
199
203
continue ;
200
204
}
205
+ if duration >= longer_than {
206
+ writeln ! ( out, "{} {:6}ms - {}" , indent, duration. as_millis( ) , msg)
207
+ . expect ( "printing profiling info to stdout" ) ;
201
208
202
- writeln ! ( out, "{} {:6}ms - {}" , indent, dur. as_millis( ) , msg)
203
- . expect ( "printing profiling info to stdout" ) ;
209
+ print ( lvl + 1 , & msgs[ last..i] , out, longer_than) ;
210
+ } else {
211
+ short. push ( ( msg, duration) )
212
+ }
204
213
205
- print ( lvl + 1 , & msgs[ last..i] , out) ;
206
214
last = i;
207
215
}
216
+ short. sort_by_key ( |( msg, _time) | * msg) ;
217
+ for ( msg, entires) in short. iter ( ) . group_by ( |( msg, _time) | msg) . into_iter ( ) {
218
+ let mut count = 0 ;
219
+ let mut total_duration = Duration :: default ( ) ;
220
+ entires. for_each ( |( _msg, time) | {
221
+ count += 1 ;
222
+ total_duration += * time;
223
+ } ) ;
224
+ writeln ! ( out, "{} {:6}ms - {} ({} calls)" , indent, total_duration. as_millis( ) , msg, count)
225
+ . expect ( "printing profiling info to stdout" ) ;
226
+ }
208
227
}
209
228
210
229
#[ cfg( test) ]
0 commit comments