diff options
author | Matt Cross <mat.cross@gmail.com> | 2015-03-26 16:13:56 -0400 |
---|---|---|
committer | Matt Cross <matt.cross@cacheio.com> | 2015-03-26 16:24:11 -0400 |
commit | 6ce10a2a05f13803061538d5c77e89695de59be4 (patch) | |
tree | 1b46b0da2c951c16837c45e5eea0cdee12107659 | |
parent | 2c1a165fa56a6f8dff8fa2662ceda971ad676ead (diff) | |
download | gperftools-6ce10a2a05f13803061538d5c77e89695de59be4.tar.gz |
Add support for printing collapsed stacks for generating flame graphs.
-rwxr-xr-x | src/pprof | 52 |
1 files changed, 52 insertions, 0 deletions
@@ -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; |