summaryrefslogtreecommitdiff
path: root/cesar/common
diff options
context:
space:
mode:
authorschodet2009-11-17 09:49:30 +0000
committerschodet2009-11-17 09:49:30 +0000
commit4ed155ea7ea1f017be65a6fb746f583f8f58c59f (patch)
tree6ce3bab85c130481666e4d223baece55b5dbf758 /cesar/common
parenta13e098ad20b0c9d450a56a8015e9f3287187351 (diff)
cesar/common/tools: add perf decoder tool
git-svn-id: svn+ssh://pessac/svn/cesar/trunk@6395 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'cesar/common')
-rwxr-xr-xcesar/common/tools/perf-decode113
1 files changed, 113 insertions, 0 deletions
diff --git a/cesar/common/tools/perf-decode b/cesar/common/tools/perf-decode
new file mode 100755
index 0000000000..6ab2922e08
--- /dev/null
+++ b/cesar/common/tools/perf-decode
@@ -0,0 +1,113 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use Getopt::Long qw(:config no_ignore_case bundling);
+use Pod::Usage;
+
+# Options parsing.
+my $help;
+my $man;
+my $scale;
+my $divisor = 25;
+my $unit = 'us';
+GetOptions (
+ 'help|h' => \$help,
+ 'man' => \$man,
+ 'scale|s=s' => \$scale,
+) or pod2usage (2);
+pod2usage (-verbose => 2) if $man;
+pod2usage (1) if $help;
+
+# Parse $scale.
+if (defined $scale)
+{
+ $scale =~ m{^(\d+)(?:/(\w+))?$} or pod2usage ('Bad --scale option.');
+ ($divisor, $unit) = ($1 + 0, $2);
+}
+
+my @stack;
+my $efmt = $unit ? "%.2f $unit" : "%d";
+
+while (<>)
+{
+ chomp;
+ # Only interested by what is inside this.
+ if (/^---trace-begin\[perf\]---$/ .. /^---trace-end---$/)
+ {
+ # But the markers are not interresting by themself.
+ next if /^---/;
+ # Get information.
+ /^\[(0x[0-9a-f]{8})\] (\w+) (.*)$/
+ or do { warn "$ARGV:$.: bad line `$_'.\n"; next; };
+ my ($date, $func, $step) = ($1, $2, $3);
+ my $idate = hex ($date);
+ my $elapsed = '';
+ # If begin, only push this information.
+ if ($step eq 'begin')
+ {
+ push @stack, { begin => $idate, date => $idate, func => $func };
+ }
+ # If stack corrupted, ignore.
+ elsif (!@stack || $stack[-1]->{func} ne $func)
+ {
+ warn "$ARGV:$.: unstacked function.\n";
+ }
+ # Else, compute elapsed time.
+ else
+ {
+ # Elapsed since last event on this stack level.
+ if ($step ne 'end' || $stack[-1]->{date} != $stack[-1]->{begin})
+ {
+ my $diff = ($idate - $stack[-1]->{date}) / $divisor;
+ $elapsed .= sprintf ' +' . $efmt, $diff;
+ }
+ # Elapsed since begin.
+ if ($step eq 'end')
+ {
+ my $diff = ($idate - $stack[-1]->{begin}) / $divisor;
+ $elapsed .= sprintf ' =' . $efmt, $diff;
+ }
+ # Update stack if not the end.
+ $stack[-1]->{date} = $idate if $step ne 'end';
+ }
+ # Print information.
+ my $indent = ' ' x $#stack;
+ print "[$date] $indent$func $step$elapsed\n";
+ # Pop if this is a function end.
+ pop @stack if $step eq 'end';
+ }
+}
+
+__END__
+
+=head1 NAME
+
+perf-decode - Decode perf traces
+
+=head1 SYNOPSIS
+
+perf-decode [options] [files...]
+
+ Options:
+ -h, --help brief help message
+ --man output manual
+ -s, --scale=DIVISOR[/UNIT] scale factor and optional unit
+
+=head1 DESCRIPTION
+
+This script will read trace output from the lib/perf module and format it for
+easy analysis. This includes:
+
+=over
+
+=item - automatic indentation,
+
+=item - compute time elapsed since last event at the same stack level
+(prefixed with '+'),
+
+=item - compute time elapsed since function begin (prefixed with '=').
+
+=back
+
+=cut
+