~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to misc/pprof

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
81
81
 
82
82
my $PPROF_VERSION = "1.5";
83
83
 
 
84
# NOTE: All mentions of c++filt have been expunged from this script
 
85
# because (1) we don't use C++, and (2) the copy of c++filt that ships
 
86
# on OS X is from 2007 and destroys nm output by "demangling" the
 
87
# first two columns (address and symbol type).
 
88
 
84
89
# These are the object tools we use which can come from a
85
90
# user-specified location using --tools, from the PPROF_TOOLS
86
91
# environment variable, or from the environment.
88
93
  "objdump" => "objdump",
89
94
  "nm" => "nm",
90
95
  "addr2line" => "addr2line",
91
 
  "c++filt" => "c++filt",
92
96
  ## ConfigureObjTools may add architecture-specific entries:
93
97
  #"nm_pdb" => "nm-pdb",       # for reading windows (PDB-format) executables
94
98
  #"addr2line_pdb" => "addr2line-pdb",                                # ditto
634
638
      # (only matters when --heapcheck is given but we must be
635
639
      # compatible with old branches that did not pass --heapcheck always):
636
640
      if ($total != 0) {
637
 
        printf("Total: %s %s\n", Unparse($total), Units());
 
641
        Infof("Total: %s %s\n", Unparse($total), Units());
638
642
      }
639
643
      PrintText($symbols, $flat, $cumulative, $total, -1);
640
644
    } elsif ($main::opt_raw) {
726
730
    "firefox",
727
731
  );
728
732
  foreach my $b (@alt) {
729
 
    if (-f $b) {
730
 
      if (system($b, $fname) == 0) {
731
 
        return;
732
 
      }
 
733
    if (system($b, $fname) == 0) {
 
734
      return;
733
735
    }
734
736
  }
735
737
 
931
933
  if ($focus ne '') {
932
934
    $profile = FocusProfile($symbols, $profile, $focus);
933
935
    my $focus_count = TotalProfile($profile);
934
 
    printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n",
 
936
    Infof("After focusing on '%s': %s %s of %s (%0.1f%%)\n",
935
937
           $focus,
936
938
           Unparse($focus_count), Units(),
937
939
           Unparse($total_count), ($focus_count*100.0) / $total_count);
939
941
  if ($ignore ne '') {
940
942
    $profile = IgnoreProfile($symbols, $profile, $ignore);
941
943
    my $ignore_count = TotalProfile($profile);
942
 
    printf("After ignoring '%s': %s %s of %s (%0.1f%%)\n",
 
944
    Infof("After ignoring '%s': %s %s of %s (%0.1f%%)\n",
943
945
           $ignore,
944
946
           Unparse($ignore_count), Units(),
945
947
           Unparse($total_count),
1115
1117
  }
1116
1118
}
1117
1119
 
 
1120
# Print information conditionally filtered out depending on the output
 
1121
# format.
 
1122
sub Infof {
 
1123
  my $format = shift;
 
1124
  my @args = @_;
 
1125
  return if $main::opt_svg;
 
1126
  printf($format, @args);
 
1127
}
 
1128
 
1118
1129
# Print text output
1119
1130
sub PrintText {
1120
1131
  my $symbols = shift;
2638
2649
                      'runtime.makemap_c',
2639
2650
                      'runtime.makeslice',
2640
2651
                      'runtime.mal',
 
2652
                      'runtime.settype',
 
2653
                      'runtime.settype_flush',
2641
2654
                      'runtime.slicebytetostring',
2642
2655
                      'runtime.sliceinttostring',
2643
2656
                      'runtime.stringtoslicebyte',
2971
2984
 
2972
2985
sub IsProfileURL {
2973
2986
  my $profile_name = shift;
2974
 
  my ($host, $port, $prefix, $path) = ParseProfileURL($profile_name);
 
2987
  my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($profile_name);
2975
2988
  return defined($host) and defined($port) and defined($path);
2976
2989
}
2977
2990
 
2978
2991
sub ParseProfileURL {
2979
2992
  my $profile_name = shift;
2980
2993
  if (defined($profile_name) &&
2981
 
      $profile_name =~ m,^(http://|)([^/:]+):(\d+)(|\@\d+)(|/|(.*?)($PROFILE_PAGE|$PMUPROFILE_PAGE|$HEAP_PAGE|$GROWTH_PAGE|$THREAD_PAGE|$CONTENTION_PAGE|$WALL_PAGE|$FILTEREDPROFILE_PAGE))$,o) {
 
2994
      $profile_name =~ m,^(?:(https?)://|)([^/:]+):(\d+)(|\@\d+)(|/|(.*?)($PROFILE_PAGE|$PMUPROFILE_PAGE|$HEAP_PAGE|$GROWTH_PAGE|$THREAD_PAGE|$CONTENTION_PAGE|$WALL_PAGE|$FILTEREDPROFILE_PAGE))$,o) {
2982
2995
    # $7 is $PROFILE_PAGE/$HEAP_PAGE/etc.  $5 is *everything* after
2983
2996
    # the hostname, as long as that everything is the empty string,
2984
2997
    # a slash, or something ending in $PROFILE_PAGE/$HEAP_PAGE/etc.
2985
2998
    # So "$7 || $5" is $PROFILE_PAGE/etc if there, or else it's "/" or "".
2986
 
    return ($2, $3, $6, $7 || $5);
 
2999
    return ($1 || "http", $2, $3, $6, $7 || $5);
2987
3000
  }
2988
3001
  return ();
2989
3002
}
2990
3003
 
2991
3004
# We fetch symbols from the first profile argument.
2992
3005
sub SymbolPageURL {
2993
 
  my ($host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
2994
 
  return "http://$host:$port$prefix$SYMBOL_PAGE";
 
3006
  my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
 
3007
  return "$scheme://$host:$port$prefix$SYMBOL_PAGE";
2995
3008
}
2996
3009
 
2997
3010
sub FetchProgramName() {
2998
 
  my ($host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
2999
 
  my $url = "http://$host:$port$prefix$PROGRAM_NAME_PAGE";
 
3011
  my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]);
 
3012
  my $url = "$scheme://$host:$port$prefix$PROGRAM_NAME_PAGE";
3000
3013
  my $command_line = "$CURL -s '$url'";
3001
3014
  open(CMDLINE, "$command_line |") or error($command_line);
3002
3015
  my $cmdline = <CMDLINE>;
3084
3097
    my $url = SymbolPageURL();
3085
3098
    $url = ResolveRedirectionForCurl($url);
3086
3099
    my $command_line = "$CURL -sd '\@$main::tmpfile_sym' '$url'";
3087
 
    # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols.
3088
 
    my $cppfilt = $obj_tool_map{"c++filt"};
3089
 
    open(SYMBOL, "$command_line | $cppfilt |") or error($command_line);
 
3100
    open(SYMBOL, "$command_line |") or error($command_line);
3090
3101
    ReadSymbols(*SYMBOL{IO}, $symbol_map);
3091
3102
    close(SYMBOL);
3092
3103
  }
3128
3139
 
3129
3140
sub MakeProfileBaseName {
3130
3141
  my ($binary_name, $profile_name) = @_;
3131
 
  my ($host, $port, $prefix, $path) = ParseProfileURL($profile_name);
 
3142
  my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($profile_name);
3132
3143
  my $binary_shortname = BaseName($binary_name);
3133
3144
  return sprintf("%s.%s.%s-port%s",
3134
3145
                 $binary_shortname, $main::op_time, $host, $port);
3143
3154
  if (!IsProfileURL($profile_name)) {
3144
3155
    return $profile_name;
3145
3156
  } else {
3146
 
    my ($host, $port, $prefix, $path) = ParseProfileURL($profile_name);
 
3157
    my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($profile_name);
3147
3158
    if ($path eq "" || $path eq "/") {
3148
3159
      # Missing type specifier defaults to cpu-profile
3149
3160
      $path = $PROFILE_PAGE;
3155
3166
    my $curl_timeout;
3156
3167
    if (($path =~ m/$PROFILE_PAGE/) || ($path =~ m/$PMUPROFILE_PAGE/)) {
3157
3168
      if ($path =~ m/$PROFILE_PAGE/) {
3158
 
        $url = sprintf("http://$host:$port$prefix$path?seconds=%d",
 
3169
        $url = sprintf("$scheme://$host:$port$prefix$path?seconds=%d",
3159
3170
            $main::opt_seconds);
3160
3171
      } else {
3161
3172
        if ($profile_name =~ m/[?]/) {
3163
3174
        } else {
3164
3175
          $profile_name .= "?"
3165
3176
        }
3166
 
        $url = sprintf("http://$profile_name" . "seconds=%d",
 
3177
        $url = sprintf("$scheme://$profile_name" . "seconds=%d",
3167
3178
            $main::opt_seconds);
3168
3179
      }
3169
3180
      $curl_timeout = sprintf("--max-time %d",
3174
3185
      my $suffix = $path;
3175
3186
      $suffix =~ s,/,.,g;
3176
3187
      $profile_file .= "$suffix";
3177
 
      $url = "http://$host:$port$prefix$path";
 
3188
      $url = "$scheme://$host:$port$prefix$path";
3178
3189
      $curl_timeout = "";
3179
3190
    }
3180
3191
 
3201
3212
    }
3202
3213
 
3203
3214
    (system($cmd) == 0) || error("Failed to get profile: $cmd: $!\n");
 
3215
    open(TMPPROF, "$tmp_profile") || error("Cannot open $tmp_profile: $!\n");
 
3216
    my $line = <TMPPROF>;
 
3217
    close(TMPPROF);
 
3218
    $line !~ /^Could not enable CPU profiling/ || error($line);
3204
3219
    (system("mv $tmp_profile $real_profile") == 0) || error("Unable to rename profile\n");
3205
3220
    print STDERR "Wrote profile to $real_profile\n";
3206
3221
    $main::collected_profile = $real_profile;
3753
3768
        } else {
3754
3769
          # Remote-heap version 1
3755
3770
          my $ratio;
3756
 
          $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
3757
 
          if ($ratio < 1) {
3758
 
            $n1 /= $ratio;
3759
 
            $s1 /= $ratio;
 
3771
          if ($n1 > 0) {
 
3772
            $ratio = (($s1*1.0)/$n1)/($sample_adjustment);
 
3773
            if ($ratio < 1) {
 
3774
                $n1 /= $ratio;
 
3775
                $s1 /= $ratio;
 
3776
            }
3760
3777
          }
3761
 
          $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
3762
 
          if ($ratio < 1) {
3763
 
            $n2 /= $ratio;
3764
 
            $s2 /= $ratio;
 
3778
          if ($n2 > 0) {
 
3779
            $ratio = (($s2*1.0)/$n2)/($sample_adjustment);
 
3780
            if ($ratio < 1) {
 
3781
                $n2 /= $ratio;
 
3782
                $s2 /= $ratio;
 
3783
            }
3765
3784
          }
3766
3785
        }
3767
3786
      }
4398
4417
    $cmd = "$addr2line --demangle -f -C -e $image";
4399
4418
  }
4400
4419
 
4401
 
  if (system("$addr2line --help >/dev/null 2>&1") != 0) {
4402
 
    # addr2line must not exist.  Fall back to go tool addr2line.
4403
 
    $addr2line = "go tool addr2line";
4404
 
    $cmd = "$addr2line $image";
4405
 
  }
 
4420
  # Use the go version because we know it works on all platforms
 
4421
  $addr2line = "go tool addr2line";
 
4422
  $cmd = "$addr2line $image";
4406
4423
 
4407
4424
  # If "addr2line" isn't installed on the system at all, just use
4408
4425
  # nm to get what info we can (function names, but not line numbers).
4595
4612
    # in the same directory as pprof.
4596
4613
    $obj_tool_map{"nm_pdb"} = "nm-pdb";
4597
4614
    $obj_tool_map{"addr2line_pdb"} = "addr2line-pdb";
 
4615
    $obj_tool_map{"is_windows"} = "true";
4598
4616
  }
4599
4617
 
4600
4618
  if ($file_type =~ /Mach-O/) {
4772
4790
  }
4773
4791
 
4774
4792
  my $nm = $obj_tool_map{"nm"};
4775
 
  my $cppfilt = $obj_tool_map{"c++filt"};
4776
4793
 
4777
4794
  # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm
4778
4795
  # binary doesn't support --demangle.  In addition, for OS X we need
4781
4798
  # in an incompatible way.  So first we test whether our nm supports
4782
4799
  # --demangle and -f.
4783
4800
  my $demangle_flag = "";
4784
 
  my $cppfilt_flag = "";
4785
4801
  if (system("$nm --demangle $image >/dev/null 2>&1") == 0) {
4786
4802
    # In this mode, we do "nm --demangle <foo>"
4787
4803
    $demangle_flag = "--demangle";
4788
 
    $cppfilt_flag = "";
4789
 
  } elsif (system("$cppfilt $image >/dev/null 2>&1") == 0) {
4790
 
    # In this mode, we do "nm <foo> | c++filt"
4791
 
    $cppfilt_flag = " | $cppfilt";
4792
 
  };
 
4804
  }
4793
4805
  my $flatten_flag = "";
4794
4806
  if (system("$nm -f $image >/dev/null 2>&1") == 0) {
4795
4807
    $flatten_flag = "-f";
4796
4808
  }
4797
4809
 
4798
 
  # Finally, in the case $imagie isn't a debug library, we try again with
4799
 
  # -D to at least get *exported* symbols.  If we can't use --demangle,
4800
 
  # we use c++filt instead, if it exists on this system.
 
4810
  # Finally, in the case $image isn't a debug library, we try again with
 
4811
  # -D to at least get *exported* symbols.  If we can't use --demangle, too bad.
4801
4812
  my @nm_commands = ("$nm -n $flatten_flag $demangle_flag" .
4802
 
                     " $image 2>/dev/null $cppfilt_flag",
 
4813
                     " $image 2>/dev/null",
4803
4814
                     "$nm -D -n $flatten_flag $demangle_flag" .
4804
 
                     " $image 2>/dev/null $cppfilt_flag",
4805
 
                     # 6nm is for Go binaries
4806
 
                     "6nm $image 2>/dev/null | sort");
 
4815
                     " $image 2>/dev/null",
 
4816
                     # go tool nm is for Go binaries
 
4817
                     "go tool nm $image 2>/dev/null | sort");
4807
4818
 
4808
 
  # If the executable is an MS Windows PDB-format executable, we'll
4809
 
  # have set up obj_tool_map("nm_pdb").  In this case, we actually
4810
 
  # want to use both unix nm and windows-specific nm_pdb, since
4811
 
  # PDB-format executables can apparently include dwarf .o files.
4812
 
  if (exists $obj_tool_map{"nm_pdb"}) {
4813
 
    my $nm_pdb = $obj_tool_map{"nm_pdb"};
4814
 
    push(@nm_commands, "$nm_pdb --demangle $image 2>/dev/null");
 
4819
  # If the executable is an MS Windows Go executable, we'll
 
4820
  # have set up obj_tool_map("is_windows").
 
4821
  if (exists $obj_tool_map{"is_windows"}) {
 
4822
    @nm_commands = ("go tool nm $image 2>/dev/null | sort");
4815
4823
  }
4816
4824
 
4817
4825
  foreach my $nm_command (@nm_commands) {