@@ -2,10 +2,9 @@ use std::cmp::Ordering;
2
2
use std:: collections:: HashMap ;
3
3
use std:: fmt:: Write ;
4
4
use std:: fs;
5
- use std:: fs:: File ;
6
5
use std:: ops:: Deref ;
7
6
use std:: path:: Path ;
8
- use std:: process:: { Command , Stdio } ;
7
+ use std:: process:: Command ;
9
8
10
9
use anyhow:: { anyhow, bail, Context } ;
11
10
use askama:: Template ;
@@ -554,7 +553,7 @@ fn compare_results(
554
553
} ;
555
554
556
555
let cachegrind_diff = if scenario_kind == ScenarioKind :: Icount {
557
- Some ( cachegrind_diff ( job_output_path, scenario) ?)
556
+ Some ( callgrind_diff ( job_output_path, scenario) ?)
558
557
} else {
559
558
None
560
559
} ;
@@ -604,68 +603,56 @@ fn split_on_threshold(diffs: Vec<ScenarioDiff>) -> (Vec<ScenarioDiff>, Vec<Scena
604
603
}
605
604
606
605
/// Returns the detailed instruction diff between the baseline and the candidate
607
- pub fn cachegrind_diff ( job_output_path : & Path , scenario : & str ) -> anyhow:: Result < String > {
608
- // The latest version of valgrind has deprecated cg_diff, which has been superseded by
609
- // cg_annotate. Many systems are running older versions, though, so we are sticking with cg_diff
610
- // for the time being.
611
-
612
- let diffs_path = job_output_path. join ( "diffs" ) ;
613
- fs:: create_dir_all ( & diffs_path) . context ( "failed to create dir for cg_diff output" ) ?;
614
-
615
- let baseline_cachegrind_file_path = job_output_path
616
- . join ( "base/results/cachegrind" )
617
- . join ( scenario) ;
618
- let candidate_cachegrind_file_path = job_output_path
619
- . join ( "candidate/results/cachegrind" )
620
- . join ( scenario) ;
621
- let diff_file_path = diffs_path. join ( scenario) ;
622
-
623
- // cg_diff generates a diff between two cachegrind output files in a custom format that is not
624
- // user-friendly
625
- let diff_file = File :: create ( & diff_file_path) . context ( "cannot create temp file for cg_diff" ) ?;
626
- let cg_diff = Command :: new ( "cg_diff" )
627
- // remove per-compilation uniqueness in symbols, eg
628
- // _ZN9hashbrown3raw21RawTable$LT$T$C$A$GT$14reserve_rehash17hc60392f3f3eac4b2E.llvm.9716880419886440089 ->
629
- // _ZN9hashbrown3raw21RawTable$LT$T$C$A$GT$14reserve_rehashE
630
- . arg ( "--mod-funcname=s/17h[0-9a-f]+E\\ .llvm\\ .\\ d+/E/" )
631
- // remove the leading path, which is unique for each checkout of the repository (we replace it by `rustls`)
632
- . arg ( "--mod-filename=s/.+\\ /(target\\ /release\\ /build.+)/rustls\\ /\\ 1/" )
633
- . arg ( baseline_cachegrind_file_path)
634
- . arg ( candidate_cachegrind_file_path)
635
- . stdout ( Stdio :: from ( diff_file) )
636
- . spawn ( )
637
- . context ( "cannot spawn cg_diff subprocess" ) ?
638
- . wait ( )
639
- . context ( "error waiting for cg_diff to finish" ) ?;
640
-
641
- if !cg_diff. success ( ) {
642
- bail ! (
643
- "cg_diff finished with an error (code = {:?})" ,
644
- cg_diff. code( )
606
+ pub fn callgrind_diff ( job_output_path : & Path , scenario : & str ) -> anyhow:: Result < String > {
607
+ // callgrind_annotate formats the callgrind output file, suitable for comparison with
608
+ // callgrind_differ
609
+ let callgrind_annotate_base = Command :: new ( "callgrind_annotate" )
610
+ . arg (
611
+ job_output_path
612
+ . join ( "base/results/callgrind" )
613
+ . join ( scenario) ,
645
614
)
646
- }
647
-
648
- // cg_annotate transforms the output of cg_diff into something a user can understand
649
- let cg_annotate = Command :: new ( "cg_annotate" )
650
- . arg ( diff_file_path)
615
+ // do not annotate source, to keep output compact
651
616
. arg ( "--auto=no" )
652
617
. output ( )
653
- . context ( "error waiting for cg_annotate to finish" ) ?;
618
+ . context ( "error waiting for callgrind_annotate to finish" ) ?;
654
619
655
- let stdout =
656
- String :: from_utf8 ( cg_annotate. stdout ) . context ( "cg_annotate produced invalid UTF8" ) ?;
620
+ let callgrind_annotate_candidate = Command :: new ( "callgrind_annotate" )
621
+ . arg (
622
+ job_output_path
623
+ . join ( "candidate/results/callgrind" )
624
+ . join ( scenario) ,
625
+ )
626
+ // do not annotate source, to keep output compact
627
+ . arg ( "--auto=no" )
628
+ . output ( )
629
+ . context ( "error waiting for callgrind_annotate to finish" ) ?;
657
630
658
- if !cg_annotate. status . success ( ) {
659
- let stderr =
660
- String :: from_utf8 ( cg_annotate. stderr ) . context ( "cg_annotate produced invalid UTF8" ) ?;
631
+ if !callgrind_annotate_base. status . success ( ) {
632
+ anyhow:: bail!(
633
+ "callgrind_annotate for base finished with an error (code = {:?})" ,
634
+ callgrind_annotate_base. status. code( )
635
+ )
636
+ }
661
637
662
- bail ! (
663
- "cg_annotate finished with an error (code = {:?}). Stdout:\n {stdout}\n Stderr:\n {stderr}" ,
664
- cg_annotate. status. code( )
638
+ if !callgrind_annotate_candidate. status . success ( ) {
639
+ anyhow:: bail!(
640
+ "callgrind_annotate for candidate finished with an error (code = {:?})" ,
641
+ callgrind_annotate_candidate. status. code( )
665
642
)
666
643
}
667
644
668
- Ok ( stdout)
645
+ let string_base = String :: from_utf8 ( callgrind_annotate_base. stdout )
646
+ . context ( "callgrind_annotate produced invalid UTF8" ) ?;
647
+ let string_candidate = String :: from_utf8 ( callgrind_annotate_candidate. stdout )
648
+ . context ( "callgrind_annotate produced invalid UTF8" ) ?;
649
+
650
+ // TODO: reinstate actual diffing, using `callgrind_differ` crate
651
+ Ok ( format ! (
652
+ "Base output:\n {string_base}\n \
653
+ =====\n \n \
654
+ Candidate output:\n {string_candidate}\n "
655
+ ) )
669
656
}
670
657
671
658
#[ derive( Template ) ]
0 commit comments