summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Cross <mat.cross@gmail.com>2015-03-26 16:13:56 -0400
committerMatt Cross <matt.cross@cacheio.com>2015-03-26 16:24:11 -0400
commit6ce10a2a05f13803061538d5c77e89695de59be4 (patch)
tree1b46b0da2c951c16837c45e5eea0cdee12107659
parent2c1a165fa56a6f8dff8fa2662ceda971ad676ead (diff)
downloadgperftools-6ce10a2a05f13803061538d5c77e89695de59be4.tar.gz
Add support for printing collapsed stacks for generating flame graphs.
-rwxr-xr-xsrc/pprof52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/pprof b/src/pprof
index 5a22c3c..c0c64bc 100755
--- a/src/pprof
+++ b/src/pprof
@@ -209,6 +209,8 @@ Output type:
--svg Generate SVG to stdout
--gif Generate GIF to stdout
--raw Generate symbolized pprof data (useful with remote fetch)
+ --collapsed Generate collapsed stacks for building flame graphs
+ (see http://www.brendangregg.com/flamegraphs.html)
Heap-Profile Options:
--inuse_space Display in-use (mega)bytes [default]
@@ -338,6 +340,7 @@ sub Init() {
$main::opt_gif = 0;
$main::opt_svg = 0;
$main::opt_raw = 0;
+ $main::opt_collapsed = 0;
$main::opt_nodecount = 80;
$main::opt_nodefraction = 0.005;
@@ -414,6 +417,7 @@ sub Init() {
"svg!" => \$main::opt_svg,
"gif!" => \$main::opt_gif,
"raw!" => \$main::opt_raw,
+ "collapsed!" => \$main::opt_collapsed,
"interactive!" => \$main::opt_interactive,
"nodecount=i" => \$main::opt_nodecount,
"nodefraction=f" => \$main::opt_nodefraction,
@@ -497,6 +501,7 @@ sub Init() {
$main::opt_svg +
$main::opt_gif +
$main::opt_raw +
+ $main::opt_collapsed +
$main::opt_interactive +
0;
if ($modes > 1) {
@@ -685,6 +690,8 @@ sub Main() {
PrintText($symbols, $flat, $cumulative, -1);
} elsif ($main::opt_raw) {
PrintSymbolizedProfile($symbols, $profile, $main::prog);
+ } elsif ($main::opt_collapsed) {
+ PrintCollapsedStacks($symbols, $profile);
} elsif ($main::opt_callgrind) {
PrintCallgrind($calls);
} else {
@@ -2855,6 +2862,40 @@ sub ExtractSymbolLocationInlineStack {
}
}
+sub ExtractSymbolNameInlineStack {
+ my $symbols = shift;
+ my $address = shift;
+
+ my @stack = ();
+
+ if (exists $symbols->{$address}) {
+ my @localinlinestack = @{$symbols->{$address}};
+ for (my $i = $#localinlinestack; $i > 0; $i-=3) {
+ my $file = $localinlinestack[$i-1];
+ my $fn = $localinlinestack[$i-0];
+
+ if ($file eq "?" || $file eq ":0") {
+ $file = "??:0";
+ }
+ if ($fn eq '??') {
+ # If we can't get the symbol name, at least use the file information.
+ $fn = $file;
+ }
+ my $suffix = "[inline]";
+ if ($i == 2) {
+ $suffix = "";
+ }
+ push (@stack, $fn.$suffix);
+ }
+ }
+ else {
+ # If we can't get a symbol name, at least fill in the address.
+ push (@stack, $address);
+ }
+
+ return @stack;
+}
+
sub ExtractSymbolLocation {
my $symbols = shift;
my $address = shift;
@@ -2904,6 +2945,17 @@ sub PrintStacksForText {
}
}
+sub PrintCollapsedStacks {
+ my $symbols = shift;
+ my $profile = shift;
+
+ while (my ($stack_trace, $count) = each %$profile) {
+ my @address = split(/\n/, $stack_trace);
+ my @names = reverse ( map { ExtractSymbolNameInlineStack($symbols, $_) } @address );
+ printf("%s %d\n", join(";", @names), $count);
+ }
+}
+
sub RemoveUninterestingFrames {
my $symbols = shift;
my $profile = shift;