From c7b956bbbaff0c4616c7bf80a5b723a58b55bbf6 Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Fri, 9 Sep 2011 20:18:45 -0700 Subject: [PATCH] adjust TEST's valgrind invocation to also work with linux's perf stat Move --log-fd=3 option from unconditional invocation into VG_OPTS default value. A future version of perf will understand --log-fd=3, but other tools probably will not, with this we can accommodate them, and the current version of perf. Makefile.SH: Set VALGRIND var conditionally, to allow cmdline override (this is probably non-portable, will need review at least). perl.valgrind.config target's test of $(VALGRIND) is simplified to use $(VG_TEST), which defaults to its legacy value: ./perl -e 1 2>/dev/null. Setting it to '--help' is needed for perf, and would also work to verify that valgrind is runnable, but current test is slightly more comprehensive for valgrind, so Ive left that for user to change in the environment. t/TEST: 1. --log-fd=3 is in default, but can be overridden by setting VG_OPTS 2. several variable renames to clarify purpose 3. $toolnm to rename output file with flexible suffix, ie: valgrind, cachegrind, perf-stat 4. add perf to cachegrind as a special case, avoid culling of valgrind output files by their content With above, and following env, make test.valgrind works: # --log-fd isnt mainline yet. VALGRIND=/home/jimc/projects/lx/linux-2.6/tools/perf/perf VG_TEST=--help VG_OPTS='stat --log-fd=3 -- ' $> make test.valgrind; PERL_VALGRIND=1 VALGRIND='/home/jimc/projects/lx/linux-2.6/tools/perf/perf' ./runtests choose t/base/cond....................................................ok t/base/if......................................................ok t/base/lex.....................................................ok ... [jimc@groucho perl]$ cat t/base/*.perf-stat Performance counter stats for './perl base/cond.t': 5.882071 task-clock # 0.850 CPUs utilized 1 context-switches # 0.000 M/sec 1 CPU-migrations # 0.000 M/sec 483 page-faults # 0.082 M/sec 4,688,843 cycles # 0.797 GHz stalled-cycles-frontend stalled-cycles-backend 3,368,118 instructions # 0.72 insns per cycle 718,821 branches # 122.205 M/sec 48,053 branch-misses # 6.68% of all branches 0.006920536 seconds time elapsed This patch will allow you to use released version of perf, just drop the --log-fd from VG_OPTS. The tests will fail, because perf will write to STDOUT, and foul the harness. The following runs cachegrind, creates t/*/*.cachegrind files. It is much slower than using perf-stat. $> export VG_OPTS='--tool=cachegrind --log-fd=3 -- ' $> make test.valgrind ==25822== Cachegrind, a cache and branch-prediction profiler ==25822== Copyright (C) 2002-2009, and GNU GPL'd, by Nicholas Nethercote et al. ==25822== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info ==25822== Command: ./perl base/cond.t ==25822== ==25822== ==25822== I refs: 1,680,072 ==25822== I1 misses: 8,129 ==25822== L2i misses: 3,675 ==25822== I1 miss rate: 0.48% ==25822== L2i miss rate: 0.21% ==25822== ==25822== D refs: 604,393 (400,033 rd + 204,360 wr) ==25822== D1 misses: 12,599 ( 8,838 rd + 3,761 wr) ==25822== L2d misses: 6,261 ( 2,966 rd + 3,295 wr) ==25822== D1 miss rate: 2.0% ( 2.2% + 1.8% ) ==25822== L2d miss rate: 1.0% ( 0.7% + 1.6% ) ==25822== ==25822== L2 refs: 20,728 ( 16,967 rd + 3,761 wr) ==25822== L2 misses: 9,936 ( 6,641 rd + 3,295 wr) ==25822== L2 miss rate: 0.4% ( 0.3% + 1.6% ) NB: The following almost works; t runs the 1st test 5 times, and produces 1 statistics file, but it fails, because TEST sees multiple leaders, (FAILED--seen duplicate leader) and exits immediately, because it happens in t/base. A work-around is easy enough, but adds yet another knob. TBD. $> VALGRIND=perf VG_OPTS='stat -r5 --log-fd=3 --' make test.valgrind Performance counter stats for './perl base/cond.t' (5 runs): 5.568965 task-clock # 0.833 CPUs utilized ( +- 1.82% ) 0 context-switches # 0.000 M/sec ( +- 61.24% ) 0 CPU-migrations # 0.000 M/sec ( +-100.00% ) 478 page-faults # 0.086 M/sec ( +- 0.37% ) 4,441,737 cycles # 0.798 GHz ( +- 1.84% ) stalled-cycles-frontend stalled-cycles-backend 3,183,574 instructions # 0.72 insns per cycle ( +- 2.30% ) 669,241 branches # 120.173 M/sec ( +- 2.87% ) 41,826 branch-misses # 6.25% of all branches ( +- 3.78% ) 0.006688160 seconds time elapsed ( +- 1.49% ) This patch is really a proof-of-concept; perf tool has far more capabilities than t/TEST can exploit well, but this is a start, and makes perf foo experimentation easier. --- Makefile.SH | 5 +++-- t/TEST | 36 ++++++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/Makefile.SH b/Makefile.SH index 18ef6aae080..7c8b5458b18 100755 --- a/Makefile.SH +++ b/Makefile.SH @@ -333,7 +333,8 @@ $make_set_make # If you're going to use valgrind and it can't be invoked as plain valgrind # then you'll need to change this, or override it on the make command line. -VALGRIND=valgrind +VALGRIND ?= valgrind +VG_TEST ?= ./perl -e 1 2>/dev/null DTRACE = $dtrace DTRACE_H = $dtrace_h @@ -887,7 +888,7 @@ perl.valgrind.config: config.sh @grep "^usemymalloc=" config.sh @grep "^usemymalloc='n'" config.sh >/dev/null || exit 1 @echo "And of course you have to have valgrind..." - $(VALGRIND) ./perl -e 1 2>/dev/null || exit 1 + $(VALGRIND) $(VG_TEST) || exit 1 # Third Degree Perl (Tru64 only) diff --git a/t/TEST b/t/TEST index a691a377ac2..0a354bade29 100755 --- a/t/TEST +++ b/t/TEST @@ -291,12 +291,13 @@ sub _cmd { if ($ENV{PERL_VALGRIND}) { my $perl_supp = $options->{return_dir} ? "$options->{return_dir}/perl.supp" : "perl.supp"; - my $valgrind = $ENV{VALGRIND} // 'valgrind'; + my $valgrind_exe = $ENV{VALGRIND} // 'valgrind'; my $vg_opts = $ENV{VG_OPTS} - // "--suppressions=$perl_supp --leak-check=yes " - . "--leak-resolution=high --show-reachable=yes " + // '--log-fd=3 ' + . "--suppressions=$perl_supp --leak-check=yes " + . "--leak-resolution=high --show-reachable=yes " . "--num-callers=50 --track-origins=yes"; - $perl = "$valgrind --log-fd=3 $vg_opts $perl"; + $perl = "$valgrind_exe $vg_opts $perl"; $redir = "3>$Valgrind_Log"; if ($options->{run_dir}) { $Valgrind_Log = "$options->{run_dir}/$Valgrind_Log"; @@ -306,7 +307,6 @@ sub _cmd { my $args = "$options->{testswitch} $options->{switch} $options->{utf8}"; $cmd = $perl . _quote_args($args) . " $test $redir"; } - return $cmd; } @@ -516,7 +516,7 @@ EOT } # + 3 : we want three dots between the test name and the "ok" my $dotdotdot = $maxlen + 3 ; - my $valgrind = 0; + my $grind_ct = 0; # count of non-empty valgrind reports my $total_files = @tests; my $good_files = 0; my $tested_files = 0; @@ -658,7 +658,9 @@ EOT } if ($ENV{PERL_VALGRIND}) { - my @valgrind; + my $toolnm = $ENV{VALGRIND}; + $toolnm =~ s|.*/||; # keep basename + my @valgrind; # gets content of file if (-e $Valgrind_Log) { if (open(V, $Valgrind_Log)) { @valgrind = ; @@ -667,11 +669,17 @@ EOT warn "$0: Failed to open '$Valgrind_Log': $!\n"; } } - if ($ENV{VG_OPTS} =~ /cachegrind/) { - if (rename $Valgrind_Log, "$test.valgrind") { - $valgrind = $valgrind + 1; + if ($ENV{VG_OPTS} =~ /(cachegrind)/ or $toolnm =~ /(perf)/) { + $toolnm = $1; + if ($toolnm eq 'perf') { + # append perfs subcommand, not just stat + my ($sub) = split /\s/, $ENV{VG_OPTS}; + $toolnm .= "-$sub"; + } + if (rename $Valgrind_Log, "$test.$toolnm") { + $grind_ct++; } else { - warn "$0: Failed to create '$test.valgrind': $!\n"; + warn "$0: Failed to create '$test.$toolnm': $!\n"; } } elsif (@valgrind) { @@ -692,7 +700,7 @@ EOT } if ($errors or $leaks) { if (rename $Valgrind_Log, "$test.valgrind") { - $valgrind = $valgrind + 1; + $grind_ct = $grind_ct + 1; } else { warn "$0: Failed to create '$test.valgrind': $!\n"; } @@ -832,8 +840,8 @@ SHRDLU_5 } } if ($ENV{PERL_VALGRIND}) { - my $s = $valgrind == 1 ? '' : 's'; - print "$valgrind valgrind report$s created.\n", ; + my $s = $grind_ct == 1 ? '' : 's'; + print "$grind_ct valgrind report$s created.\n", ; } } exit ($::bad_files != 0);