@@ -6,7 +6,7 @@ use std::io::BufRead;
6
6
use std:: io:: Write ;
7
7
use std:: path:: Path ;
8
8
use std:: process:: Command ;
9
- use std:: { fs, process} ;
9
+ use std:: { fs, io , process} ;
10
10
11
11
// Tools usable with the profiling subcommands, and named on the command line.
12
12
#[ derive( Clone , Copy , Debug , PartialEq , clap:: ValueEnum ) ]
@@ -226,7 +226,46 @@ impl<'a> Processor for ProfileProcessor<'a> {
226
226
let cgout_file = filepath ( self . output_dir , & out_file ( "cgout" ) ) ;
227
227
let cgann_file = filepath ( self . output_dir , & out_file ( "cgann" ) ) ;
228
228
229
- fs:: copy ( & tmp_cgout_file, & cgout_file) ?;
229
+ // It's useful to filter all `file:function` entries from
230
+ // jemalloc into a single fake
231
+ // `<all-jemalloc-files>:<all-jemalloc-functions>` entry. That
232
+ // way the cost of all allocations is visible in one line,
233
+ // rather than spread across many small entries.
234
+ //
235
+ // The downside is that we don't get any annotations within
236
+ // jemalloc source files, but this is no real loss, given that
237
+ // jemalloc is basically a black box whose code we never look
238
+ // at anyway. DHAT is the best way to profile allocations.
239
+ let reader = io:: BufReader :: new ( fs:: File :: open ( & tmp_cgout_file) ?) ;
240
+ let mut writer = io:: BufWriter :: new ( fs:: File :: create ( & cgout_file) ?) ;
241
+ let mut in_jemalloc_file = false ;
242
+
243
+ // A Cachegrind profile contains `fn=<function-name>` lines,
244
+ // `fl=<filename>` lines, and everything else. We just need to
245
+ // modify the `fn=` and `fl=` lines that refer to jemalloc
246
+ // code.
247
+ for line in reader. lines ( ) {
248
+ let line = line?;
249
+ if line. starts_with ( "fl=" ) {
250
+ // All jemalloc filenames have `/jemalloc/` or
251
+ // something like `/jemalloc-sys-1e20251078fe5355/` in
252
+ // them.
253
+ in_jemalloc_file = line. contains ( "/jemalloc" ) ;
254
+ if in_jemalloc_file {
255
+ writeln ! ( writer, "fl=<all-jemalloc-files>" ) ?;
256
+ continue ;
257
+ }
258
+ } else if line. starts_with ( "fn=" ) {
259
+ // Any function within a jemalloc file is a jemalloc
260
+ // function.
261
+ if in_jemalloc_file {
262
+ writeln ! ( writer, "fn=<all-jemalloc-functions>" ) ?;
263
+ continue ;
264
+ }
265
+ }
266
+ writeln ! ( writer, "{}" , line) ?;
267
+ }
268
+ writer. flush ( ) ?;
230
269
231
270
let mut cg_annotate_cmd = Command :: new ( "cg_annotate" ) ;
232
271
cg_annotate_cmd
@@ -301,11 +340,8 @@ impl<'a> Processor for ProfileProcessor<'a> {
301
340
let tmp_eprintln_file = filepath ( data. cwd . as_ref ( ) , "eprintln" ) ;
302
341
let eprintln_file = filepath ( self . output_dir , & out_file ( "eprintln" ) ) ;
303
342
304
- let mut final_file =
305
- std:: io:: BufWriter :: new ( std:: fs:: File :: create ( & eprintln_file) ?) ;
306
- for line in
307
- std:: io:: BufReader :: new ( std:: fs:: File :: open ( & tmp_eprintln_file) ?) . lines ( )
308
- {
343
+ let mut final_file = io:: BufWriter :: new ( std:: fs:: File :: create ( & eprintln_file) ?) ;
344
+ for line in io:: BufReader :: new ( std:: fs:: File :: open ( & tmp_eprintln_file) ?) . lines ( ) {
309
345
let line = line?;
310
346
// rustc under Cargo currently ~always emits artifact
311
347
// messages -- which we don't want in final
@@ -355,7 +391,7 @@ impl<'a> Processor for ProfileProcessor<'a> {
355
391
356
392
for ( cgu, items) in & by_cgu {
357
393
let cgu_file = filepath ( & out_dir, cgu) ;
358
- let mut file = std :: io:: BufWriter :: new (
394
+ let mut file = io:: BufWriter :: new (
359
395
fs:: File :: create ( & cgu_file) . with_context ( || format ! ( "{:?}" , cgu_file) ) ?,
360
396
) ;
361
397
for ( name, linkage) in items {
0 commit comments