Expanded --sort option to take threshold args with the event names. Lets you
do things like "show functions covering 99% of all D2mr events *and* 99% of all
D2mw events" - before you could only choose the threshold for one.
Useful for me, but probably no-one else. Still mentioned it in the docs,
though.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@269 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/cachegrind/cg_annotate.in b/cachegrind/cg_annotate.in
index eb7e5dd..30cc049 100644
--- a/cachegrind/cg_annotate.in
+++ b/cachegrind/cg_annotate.in
@@ -112,15 +112,18 @@
my @sort_events;
# Map from @sort_events indices to @events indices, eg. (3,2). Same idea as
-# for @show_order
+# for @show_order.
my @sort_order;
-# Threshold; whatever event is the primary sort, we print out functions
-# representing more than this proportion of 'event' events.
-my $threshold = 99;
+# Thresholds, one for each sort event (or default to 1 if no sort events
+# specified). We print out functions and do auto-annotations until we've
+# handled this proportion of all the events thresholded.
+my @thresholds;
+
+my $default_threshold = 99;
# If on, automatically annotates all files that are involved in getting over
-# the threshold count of the primary sort event.
+# all the threshold counts.
my $auto_annotate = 0;
# Number of lines to show around each annotated line.
@@ -145,7 +148,7 @@
--show=A,B,C only show figures for events A,B,C [all]
--sort=A,B,C sort columns by events A,B,C [event column order]
--threshold=<0--100> percentage of counts (of primary sort event) we
- are interested in [$threshold%]
+ are interested in [$default_threshold%]
--auto=yes|no annotate all source files containing functions
that helped reach the event count threshold [no]
--context=N print N lines of context before and after
@@ -184,13 +187,22 @@
# --sort=A,B,C
} elsif ($arg =~ /^--sort=(.*)$/) {
@sort_events = split(/,/, $1);
+ foreach my $i (0 .. scalar @sort_events - 1) {
+ if ($sort_events[$i] =~#/.*:(\d+)$/) {
+ /.*:([\d\.]+)%?$/) {
+ my $th = $1;
+ ($th >= 0 && $th <= 100) or die($usage);
+ $sort_events[$i] =~ s/:.*//;
+ $thresholds[$i] = $th;
+ } else {
+ $thresholds[$i] = 0;
+ }
+ }
# --threshold=X (tolerates a trailing '%')
} elsif ($arg =~ /^--threshold=([\d\.]+)%?$/) {
- $threshold = $1;
- if ($threshold < 0 || $threshold > 100) {
- die($usage);
- }
+ $thresholds[0] = $1;
+ ($1 >= 0 && $1 <= 100) or die($usage);
# --auto=yes|no
} elsif ($arg =~ /^--auto=(yes|no)$/) {
@@ -242,8 +254,9 @@
# 1. If $a2->[$i] is undefined, it defaults to 0 which is what we want; we turn
# off warnings to allow this. This makes things about 10% faster than
# checking for definedness ourselves.
-# 2. We don't add a ".", even though it's value is 0, because we don't want to
-# make an $a2->[$i] that is undef become 0 unnecessarily.
+# 2. We don't add an undefined count or a ".", even though it's value is 0,
+# because we don't want to make an $a2->[$i] that is undef become 0
+# unnecessarily.
sub add_array_a_to_b ($$)
{
my ($a1, $a2) = @_;
@@ -251,7 +264,7 @@
my $n = max(scalar @$a1, scalar @$a2);
$^W = 0;
foreach my $i (0 .. $n-1) {
- $a2->[$i] += $a1->[$i] if ("." ne $a1->[$i]);
+ $a2->[$i] += $a1->[$i] if (defined $a1->[$i] && "." ne $a1->[$i]);
}
$^W = 1;
}
@@ -331,6 +344,15 @@
push(@sort_order, $events{$sort_event});
}
+ # If no --threshold args give, default to 99% for the primary sort event,
+ # and 0% for the rest.
+ if (not @thresholds) {
+ foreach my $e (@sort_order) {
+ push(@thresholds, 0);
+ }
+ $thresholds[0] = $default_threshold;
+ }
+
my $curr_file;
my $curr_fn;
my $curr_name;
@@ -424,7 +446,7 @@
print("Events recorded: @events\n");
print("Events shown: @show_events\n");
print("Event sort order: @sort_events\n");
- print("Threshold: $threshold%\n");
+ print("Thresholds: @thresholds\n");
my @include_dirs2 = @include_dirs; # copy @include_dirs
shift(@include_dirs2); # remove "" entry, which is always the first
@@ -534,7 +556,7 @@
# Prints summary and function totals (with separate column widths, so that
# function names aren't pushed over unnecessarily by huge summary figures).
# Also returns a hash containing all the files that are involved in getting the
-# events count above the threshold (ie. all the interesting ones).
+# events count above the thresholds (ie. all the interesting ones).
sub print_summary_and_fn_totals ()
{
my @fn_fullnames = keys %fn_totals;
@@ -564,29 +586,43 @@
mycmp($fn_totals{$a}, $fn_totals{$b})
} @fn_fullnames;
- # The thresholded event is the one that is the primary sort event.
+
+ # Assertion
+ (scalar @sort_order == scalar @thresholds) or
+ die("sort_order length != thresholds length:\n",
+ " @sort_order\n @thresholds\n");
+
my $threshold_files = {};
- my $threshold_event_index = $sort_order[0];
- my $threshold_total = $summary_CC->[$threshold_event_index];
- my $curr_total = 0;
+ # @curr_totals has the same shape as @sort_order and @thresholds
+ my @curr_totals = ();
+ foreach my $e (@thresholds) {
+ push(@curr_totals, 0);
+ }
# Print functions, stopping when the threshold has been reached.
foreach my $fn_name (@fn_fullnames) {
- # Stop when we've reached the threshold
- last if ($curr_total * 100 / $threshold_total >= $threshold);
+ # Stop when we've reached all the thresholds
+ my $reached_all_thresholds = 1;
+ foreach my $i (scalar @thresholds - 1) {
+ my $prop = $curr_totals[$i] * 100 / $summary_CC->[$sort_order[$i]];
+ $reached_all_thresholds &= ($prop >= $thresholds[$i]);
+ }
+ last if $reached_all_thresholds;
# Print function results
my $fn_CC = $fn_totals{$fn_name};
print_CC($fn_CC, $fn_CC_col_widths);
print(" $fn_name\n");
- # Update the threshold counting
+ # Update the threshold counts
my $filename = $fn_name;
$filename =~ s/:.+$//; # remove function name
$threshold_files->{$filename} = 1;
- $curr_total += $fn_CC->[$threshold_event_index]
- if (defined $fn_CC->[$threshold_event_index]);
+ foreach my $i (0 .. scalar @sort_order - 1) {
+ $curr_totals[$i] += $fn_CC->[$sort_order[$i]]
+ if (defined $fn_CC->[$sort_order[$i]]);
+ }
}
print("\n");
diff --git a/cachegrind/docs/manual.html b/cachegrind/docs/manual.html
index 24f0d2b..dc66721 100644
--- a/cachegrind/docs/manual.html
+++ b/cachegrind/docs/manual.html
@@ -2462,8 +2462,16 @@
<li><code>--threshold=X</code> [default: 99%] <p>
Sets the threshold for the function-by-function summary. Functions are
- shown that account for more than X% of all the primary sort events. If
- auto-annotating, also affects which files are annotated.</li><p>
+ shown that account for more than X% of the primary sort event. If
+ auto-annotating, also affects which files are annotated.
+
+ Note: thresholds can be set for more than one of the events by appending
+ any events for the <code>--sort</code> option with a colon and a number
+ (no spaces, though). E.g. if you want to see the functions that cover
+ 99% of L2 read misses and 99% of L2 write misses, use this option:
+
+ <blockquote><code>--sort=D2mr:99,D2mw:99</code></blockquote>
+ </li><p>
<li><code>--auto=no</code> [default]<br>
<code>--auto=yes</code> <p>
@@ -2568,13 +2576,21 @@
number. Valgrind can handle some files with more than 65,535 lines
correctly by making some guesses to identify line number overflows. But
some cases are beyond it, in which case you'll get a warning message
- explaining that annotations for the file might be incorrect.
+ explaining that annotations for the file might be incorrect.<p>
+ </li>
+
+ <li>If you compile some files with <code>-g</code> and some without, some
+ events that take place in a file without debug info could be attributed
+ to the last line of a file with debug info (whichever one gets placed
+ before the non-debug-info file in the executable).<p>
</li>
</ul>
+This list looks long, but these cases should be fairly rare.<p>
+
Note: stabs is not an easy format to read. If you come across bizarre
annotations that look like might be caused by a bug in the stabs reader,
-please let us know.
+please let us know.<p>
<h3>7.11 Accuracy</h3>
@@ -2594,6 +2610,10 @@
<li>It doesn't account for cache misses not visible at the instruction level,
eg. those arising from TLB misses, or speculative execution.</li><p>
+ <li>Valgrind's custom <code>malloc()</code> will allocate memory in different
+ ways to the standard <code>malloc()</code>, which could warp the results.
+ </li><p>
+
<li>The instructions <code>bts</code>, <code>btr</code> and <code>btc</code>
will incorrectly be counted as doing a data read if both the arguments
are registers, eg:
diff --git a/coregrind/docs/manual.html b/coregrind/docs/manual.html
index 24f0d2b..dc66721 100644
--- a/coregrind/docs/manual.html
+++ b/coregrind/docs/manual.html
@@ -2462,8 +2462,16 @@
<li><code>--threshold=X</code> [default: 99%] <p>
Sets the threshold for the function-by-function summary. Functions are
- shown that account for more than X% of all the primary sort events. If
- auto-annotating, also affects which files are annotated.</li><p>
+ shown that account for more than X% of the primary sort event. If
+ auto-annotating, also affects which files are annotated.
+
+ Note: thresholds can be set for more than one of the events by appending
+ any events for the <code>--sort</code> option with a colon and a number
+ (no spaces, though). E.g. if you want to see the functions that cover
+ 99% of L2 read misses and 99% of L2 write misses, use this option:
+
+ <blockquote><code>--sort=D2mr:99,D2mw:99</code></blockquote>
+ </li><p>
<li><code>--auto=no</code> [default]<br>
<code>--auto=yes</code> <p>
@@ -2568,13 +2576,21 @@
number. Valgrind can handle some files with more than 65,535 lines
correctly by making some guesses to identify line number overflows. But
some cases are beyond it, in which case you'll get a warning message
- explaining that annotations for the file might be incorrect.
+ explaining that annotations for the file might be incorrect.<p>
+ </li>
+
+ <li>If you compile some files with <code>-g</code> and some without, some
+ events that take place in a file without debug info could be attributed
+ to the last line of a file with debug info (whichever one gets placed
+ before the non-debug-info file in the executable).<p>
</li>
</ul>
+This list looks long, but these cases should be fairly rare.<p>
+
Note: stabs is not an easy format to read. If you come across bizarre
annotations that look like might be caused by a bug in the stabs reader,
-please let us know.
+please let us know.<p>
<h3>7.11 Accuracy</h3>
@@ -2594,6 +2610,10 @@
<li>It doesn't account for cache misses not visible at the instruction level,
eg. those arising from TLB misses, or speculative execution.</li><p>
+ <li>Valgrind's custom <code>malloc()</code> will allocate memory in different
+ ways to the standard <code>malloc()</code>, which could warp the results.
+ </li><p>
+
<li>The instructions <code>bts</code>, <code>btr</code> and <code>btc</code>
will incorrectly be counted as doing a data read if both the arguments
are registers, eg:
diff --git a/docs/manual.html b/docs/manual.html
index 24f0d2b..dc66721 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -2462,8 +2462,16 @@
<li><code>--threshold=X</code> [default: 99%] <p>
Sets the threshold for the function-by-function summary. Functions are
- shown that account for more than X% of all the primary sort events. If
- auto-annotating, also affects which files are annotated.</li><p>
+ shown that account for more than X% of the primary sort event. If
+ auto-annotating, also affects which files are annotated.
+
+ Note: thresholds can be set for more than one of the events by appending
+ any events for the <code>--sort</code> option with a colon and a number
+ (no spaces, though). E.g. if you want to see the functions that cover
+ 99% of L2 read misses and 99% of L2 write misses, use this option:
+
+ <blockquote><code>--sort=D2mr:99,D2mw:99</code></blockquote>
+ </li><p>
<li><code>--auto=no</code> [default]<br>
<code>--auto=yes</code> <p>
@@ -2568,13 +2576,21 @@
number. Valgrind can handle some files with more than 65,535 lines
correctly by making some guesses to identify line number overflows. But
some cases are beyond it, in which case you'll get a warning message
- explaining that annotations for the file might be incorrect.
+ explaining that annotations for the file might be incorrect.<p>
+ </li>
+
+ <li>If you compile some files with <code>-g</code> and some without, some
+ events that take place in a file without debug info could be attributed
+ to the last line of a file with debug info (whichever one gets placed
+ before the non-debug-info file in the executable).<p>
</li>
</ul>
+This list looks long, but these cases should be fairly rare.<p>
+
Note: stabs is not an easy format to read. If you come across bizarre
annotations that look like might be caused by a bug in the stabs reader,
-please let us know.
+please let us know.<p>
<h3>7.11 Accuracy</h3>
@@ -2594,6 +2610,10 @@
<li>It doesn't account for cache misses not visible at the instruction level,
eg. those arising from TLB misses, or speculative execution.</li><p>
+ <li>Valgrind's custom <code>malloc()</code> will allocate memory in different
+ ways to the standard <code>malloc()</code>, which could warp the results.
+ </li><p>
+
<li>The instructions <code>bts</code>, <code>btr</code> and <code>btc</code>
will incorrectly be counted as doing a data read if both the arguments
are registers, eg:
diff --git a/memcheck/docs/manual.html b/memcheck/docs/manual.html
index 24f0d2b..dc66721 100644
--- a/memcheck/docs/manual.html
+++ b/memcheck/docs/manual.html
@@ -2462,8 +2462,16 @@
<li><code>--threshold=X</code> [default: 99%] <p>
Sets the threshold for the function-by-function summary. Functions are
- shown that account for more than X% of all the primary sort events. If
- auto-annotating, also affects which files are annotated.</li><p>
+ shown that account for more than X% of the primary sort event. If
+ auto-annotating, also affects which files are annotated.
+
+ Note: thresholds can be set for more than one of the events by appending
+ any events for the <code>--sort</code> option with a colon and a number
+ (no spaces, though). E.g. if you want to see the functions that cover
+ 99% of L2 read misses and 99% of L2 write misses, use this option:
+
+ <blockquote><code>--sort=D2mr:99,D2mw:99</code></blockquote>
+ </li><p>
<li><code>--auto=no</code> [default]<br>
<code>--auto=yes</code> <p>
@@ -2568,13 +2576,21 @@
number. Valgrind can handle some files with more than 65,535 lines
correctly by making some guesses to identify line number overflows. But
some cases are beyond it, in which case you'll get a warning message
- explaining that annotations for the file might be incorrect.
+ explaining that annotations for the file might be incorrect.<p>
+ </li>
+
+ <li>If you compile some files with <code>-g</code> and some without, some
+ events that take place in a file without debug info could be attributed
+ to the last line of a file with debug info (whichever one gets placed
+ before the non-debug-info file in the executable).<p>
</li>
</ul>
+This list looks long, but these cases should be fairly rare.<p>
+
Note: stabs is not an easy format to read. If you come across bizarre
annotations that look like might be caused by a bug in the stabs reader,
-please let us know.
+please let us know.<p>
<h3>7.11 Accuracy</h3>
@@ -2594,6 +2610,10 @@
<li>It doesn't account for cache misses not visible at the instruction level,
eg. those arising from TLB misses, or speculative execution.</li><p>
+ <li>Valgrind's custom <code>malloc()</code> will allocate memory in different
+ ways to the standard <code>malloc()</code>, which could warp the results.
+ </li><p>
+
<li>The instructions <code>bts</code>, <code>btr</code> and <code>btc</code>
will incorrectly be counted as doing a data read if both the arguments
are registers, eg:
diff --git a/vg_annotate.in b/vg_annotate.in
index eb7e5dd..30cc049 100644
--- a/vg_annotate.in
+++ b/vg_annotate.in
@@ -112,15 +112,18 @@
my @sort_events;
# Map from @sort_events indices to @events indices, eg. (3,2). Same idea as
-# for @show_order
+# for @show_order.
my @sort_order;
-# Threshold; whatever event is the primary sort, we print out functions
-# representing more than this proportion of 'event' events.
-my $threshold = 99;
+# Thresholds, one for each sort event (or default to 1 if no sort events
+# specified). We print out functions and do auto-annotations until we've
+# handled this proportion of all the events thresholded.
+my @thresholds;
+
+my $default_threshold = 99;
# If on, automatically annotates all files that are involved in getting over
-# the threshold count of the primary sort event.
+# all the threshold counts.
my $auto_annotate = 0;
# Number of lines to show around each annotated line.
@@ -145,7 +148,7 @@
--show=A,B,C only show figures for events A,B,C [all]
--sort=A,B,C sort columns by events A,B,C [event column order]
--threshold=<0--100> percentage of counts (of primary sort event) we
- are interested in [$threshold%]
+ are interested in [$default_threshold%]
--auto=yes|no annotate all source files containing functions
that helped reach the event count threshold [no]
--context=N print N lines of context before and after
@@ -184,13 +187,22 @@
# --sort=A,B,C
} elsif ($arg =~ /^--sort=(.*)$/) {
@sort_events = split(/,/, $1);
+ foreach my $i (0 .. scalar @sort_events - 1) {
+ if ($sort_events[$i] =~#/.*:(\d+)$/) {
+ /.*:([\d\.]+)%?$/) {
+ my $th = $1;
+ ($th >= 0 && $th <= 100) or die($usage);
+ $sort_events[$i] =~ s/:.*//;
+ $thresholds[$i] = $th;
+ } else {
+ $thresholds[$i] = 0;
+ }
+ }
# --threshold=X (tolerates a trailing '%')
} elsif ($arg =~ /^--threshold=([\d\.]+)%?$/) {
- $threshold = $1;
- if ($threshold < 0 || $threshold > 100) {
- die($usage);
- }
+ $thresholds[0] = $1;
+ ($1 >= 0 && $1 <= 100) or die($usage);
# --auto=yes|no
} elsif ($arg =~ /^--auto=(yes|no)$/) {
@@ -242,8 +254,9 @@
# 1. If $a2->[$i] is undefined, it defaults to 0 which is what we want; we turn
# off warnings to allow this. This makes things about 10% faster than
# checking for definedness ourselves.
-# 2. We don't add a ".", even though it's value is 0, because we don't want to
-# make an $a2->[$i] that is undef become 0 unnecessarily.
+# 2. We don't add an undefined count or a ".", even though it's value is 0,
+# because we don't want to make an $a2->[$i] that is undef become 0
+# unnecessarily.
sub add_array_a_to_b ($$)
{
my ($a1, $a2) = @_;
@@ -251,7 +264,7 @@
my $n = max(scalar @$a1, scalar @$a2);
$^W = 0;
foreach my $i (0 .. $n-1) {
- $a2->[$i] += $a1->[$i] if ("." ne $a1->[$i]);
+ $a2->[$i] += $a1->[$i] if (defined $a1->[$i] && "." ne $a1->[$i]);
}
$^W = 1;
}
@@ -331,6 +344,15 @@
push(@sort_order, $events{$sort_event});
}
+ # If no --threshold args give, default to 99% for the primary sort event,
+ # and 0% for the rest.
+ if (not @thresholds) {
+ foreach my $e (@sort_order) {
+ push(@thresholds, 0);
+ }
+ $thresholds[0] = $default_threshold;
+ }
+
my $curr_file;
my $curr_fn;
my $curr_name;
@@ -424,7 +446,7 @@
print("Events recorded: @events\n");
print("Events shown: @show_events\n");
print("Event sort order: @sort_events\n");
- print("Threshold: $threshold%\n");
+ print("Thresholds: @thresholds\n");
my @include_dirs2 = @include_dirs; # copy @include_dirs
shift(@include_dirs2); # remove "" entry, which is always the first
@@ -534,7 +556,7 @@
# Prints summary and function totals (with separate column widths, so that
# function names aren't pushed over unnecessarily by huge summary figures).
# Also returns a hash containing all the files that are involved in getting the
-# events count above the threshold (ie. all the interesting ones).
+# events count above the thresholds (ie. all the interesting ones).
sub print_summary_and_fn_totals ()
{
my @fn_fullnames = keys %fn_totals;
@@ -564,29 +586,43 @@
mycmp($fn_totals{$a}, $fn_totals{$b})
} @fn_fullnames;
- # The thresholded event is the one that is the primary sort event.
+
+ # Assertion
+ (scalar @sort_order == scalar @thresholds) or
+ die("sort_order length != thresholds length:\n",
+ " @sort_order\n @thresholds\n");
+
my $threshold_files = {};
- my $threshold_event_index = $sort_order[0];
- my $threshold_total = $summary_CC->[$threshold_event_index];
- my $curr_total = 0;
+ # @curr_totals has the same shape as @sort_order and @thresholds
+ my @curr_totals = ();
+ foreach my $e (@thresholds) {
+ push(@curr_totals, 0);
+ }
# Print functions, stopping when the threshold has been reached.
foreach my $fn_name (@fn_fullnames) {
- # Stop when we've reached the threshold
- last if ($curr_total * 100 / $threshold_total >= $threshold);
+ # Stop when we've reached all the thresholds
+ my $reached_all_thresholds = 1;
+ foreach my $i (scalar @thresholds - 1) {
+ my $prop = $curr_totals[$i] * 100 / $summary_CC->[$sort_order[$i]];
+ $reached_all_thresholds &= ($prop >= $thresholds[$i]);
+ }
+ last if $reached_all_thresholds;
# Print function results
my $fn_CC = $fn_totals{$fn_name};
print_CC($fn_CC, $fn_CC_col_widths);
print(" $fn_name\n");
- # Update the threshold counting
+ # Update the threshold counts
my $filename = $fn_name;
$filename =~ s/:.+$//; # remove function name
$threshold_files->{$filename} = 1;
- $curr_total += $fn_CC->[$threshold_event_index]
- if (defined $fn_CC->[$threshold_event_index]);
+ foreach my $i (0 .. scalar @sort_order - 1) {
+ $curr_totals[$i] += $fn_CC->[$sort_order[$i]]
+ if (defined $fn_CC->[$sort_order[$i]]);
+ }
}
print("\n");