stackcollapse-go.pl 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #!/usr/bin/perl -w
  2. #
  3. # stackcollapse-go.pl collapse golang samples into single lines.
  4. #
  5. # Parses golang smaples generated by "go tool pprof" and outputs stacks as
  6. # single lines, with methods separated by semicolons, and then a space and an
  7. # occurrence count. For use with flamegraph.pl.
  8. #
  9. # USAGE: ./stackcollapse-go.pl infile > outfile
  10. #
  11. # Example Input:
  12. # ...
  13. # Samples:
  14. # samples/count cpu/nanoseconds
  15. # 1 10000000: 1 2
  16. # 2 10000000: 3 2
  17. # 1 10000000: 4 2
  18. # ...
  19. # Locations
  20. # 1: 0x58b265 scanblock :0 s=0
  21. # 2: 0x599530 GC :0 s=0
  22. # 3: 0x58a999 flushptrbuf :0 s=0
  23. # 4: 0x58d6a8 runtime.MSpan_Sweep :0 s=0
  24. # ...
  25. # Mappings
  26. # ...
  27. #
  28. # Example Output:
  29. #
  30. # GC;flushptrbuf 2
  31. # GC;runtime.MSpan_Sweep 1
  32. # GC;scanblock 1
  33. #
  34. # Input may contain many stacks as generated from go tool pprof:
  35. #
  36. # go tool pprof -seconds=60 -raw -output=a.pprof http://$ADDR/debug/pprof/profile
  37. #
  38. # For format of text profile, See golang/src/internal/pprof/profile/profile.go
  39. #
  40. # Copyright 2017 Sijie Yang (yangsijie@baidu.com). All rights reserved.
  41. #
  42. # This program is free software; you can redistribute it and/or
  43. # modify it under the terms of the GNU General Public License
  44. # as published by the Free Software Foundation; either version 2
  45. # of the License, or (at your option) any later version.
  46. #
  47. # This program is distributed in the hope that it will be useful,
  48. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  49. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  50. # GNU General Public License for more details.
  51. #
  52. # You should have received a copy of the GNU General Public License
  53. # along with this program; if not, write to the Free Software Foundation,
  54. # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  55. #
  56. # (http://www.gnu.org/copyleft/gpl.html)
  57. #
  58. # 16-Jan-2017 Sijie Yang Created this.
  59. use strict;
  60. use Getopt::Long;
  61. # tunables
  62. my $help = 0;
  63. sub usage {
  64. die <<USAGE_END;
  65. USAGE: $0 infile > outfile\n
  66. USAGE_END
  67. }
  68. GetOptions(
  69. 'help' => \$help,
  70. ) or usage();
  71. $help && usage();
  72. # internals
  73. my $state = "ignore";
  74. my %stacks;
  75. my %frames;
  76. my %collapsed;
  77. sub remember_stack {
  78. my ($stack, $count) = @_;
  79. $stacks{$stack} += $count;
  80. }
  81. #
  82. # Output stack string in required format. For example, for the following samples,
  83. # format_statck() would return GC;runtime.MSpan_Sweep for stack "4 2"
  84. #
  85. # Locations
  86. # 1: 0x58b265 scanblock :0 s=0
  87. # 2: 0x599530 GC :0 s=0
  88. # 3: 0x58a999 flushptrbuf :0 s=0
  89. # 4: 0x58d6a8 runtime.MSpan_Sweep :0 s=0
  90. #
  91. sub format_statck {
  92. my ($stack) = @_;
  93. my @loc_list = split(/ /, $stack);
  94. for (my $i=0; $i<=$#loc_list; $i++) {
  95. my $loc_name = $frames{$loc_list[$i]};
  96. $loc_list[$i] = $loc_name if ($loc_name);
  97. }
  98. return join(";", reverse(@loc_list));
  99. }
  100. foreach (<>) {
  101. next if m/^#/;
  102. chomp;
  103. if ($state eq "ignore") {
  104. if (/Samples:/) {
  105. $state = "sample";
  106. next;
  107. }
  108. } elsif ($state eq "sample") {
  109. if (/^\s*([0-9]+)\s*[0-9]+: ([0-9 ]+)/) {
  110. my $samples = $1;
  111. my $stack = $2;
  112. remember_stack($stack, $samples);
  113. } elsif (/Locations/) {
  114. $state = "location";
  115. next;
  116. }
  117. } elsif ($state eq "location") {
  118. if (/^\s*([0-9]*): 0x[0-9a-f]+ (M=[0-9]+ )?([^ ]+) .*/) {
  119. my $loc_id = $1;
  120. my $loc_name = $3;
  121. $frames{$loc_id} = $loc_name;
  122. } elsif (/Mappings/) {
  123. $state = "mapping";
  124. last;
  125. }
  126. }
  127. }
  128. foreach my $k (keys %stacks) {
  129. my $stack = format_statck($k);
  130. my $count = $stacks{$k};
  131. $collapsed{$stack} += $count;
  132. }
  133. foreach my $k (sort { $a cmp $b } keys %collapsed) {
  134. print "$k $collapsed{$k}\n";
  135. }