Home | History | Annotate | Line # | Download | only in Bin
      1 #!/usr/bin/perl -w
      2 #
      3 # hotuser - sample on-CPU user-level functions and libraries.
      4 #           Written using Perl and DTrace (Solaris 10 03/05)
      5 #
      6 # This samples the on-CPU function at 1001 Hertz, for a simple yet
      7 # effective user-level profiling tool for sampling exclusive function time.
      8 # The output will identify which function is on the CPU the most - which
      9 # is the hottest. See Notes/ALLexclusive_notes.txt for an explanation of
     10 # exclusive time.
     11 #
     12 # $Id: hotuser,v 1.1.1.1 2015/09/30 22:01:07 christos Exp $
     13 #
     14 # USAGE:        hotuser [-hl] { -c command | -p PID }
     15 #
     16 #		-h              # help
     17 #		-l              # match libraries, not functions
     18 #		-p PID          # examine this PID
     19 #		-c command      # run and examine this command
     20 #       eg,
     21 #		hotuser -p 81   # sample user functions from PID 81
     22 #		hotuser -lp 81  # sample user libraries from PID 81
     23 #		hotuser -p `pgrep -n Xorg`	# sample Xorg
     24 #
     25 # FIELDS:
     26 #		FUNCTION        Function name
     27 #		LIBRARY         Library name
     28 #		COUNT           Number of samples
     29 #		PCNT            Percentage of total samples
     30 #
     31 # COPYRIGHT: Copyright (c) 2006 Brendan Gregg.
     32 #
     33 # CDDL HEADER START
     34 #
     35 #  The contents of this file are subject to the terms of the
     36 #  Common Development and Distribution License, Version 1.0 only
     37 #  (the "License").  You may not use this file except in compliance
     38 #  with the License.
     39 #
     40 #  You can obtain a copy of the license at Docs/cddl1.txt
     41 #  or http://www.opensolaris.org/os/licensing.
     42 #  See the License for the specific language governing permissions
     43 #  and limitations under the License.
     44 #
     45 # CDDL HEADER END
     46 #
     47 # Author: Brendan Gregg  [Sydney, Australia]
     48 #
     49 # 29-Jun-2006	Brendan Gregg	Created this.
     50 # 29-Jun-2006	   "      "	Last update.
     51 #
     52 
     53 use strict;
     54 use Getopt::Std;
     55 
     56 #
     57 # Command Line Arguments
     58 #
     59 my $args;
     60 usage() if defined $ARGV[0] and $ARGV[0] eq "--help";
     61 getopts('c:hlp:') or usage();
     62 usage() if defined $main::opt_h and $main::opt_h;
     63 my $libs = defined $main::opt_l and $main::opt_l ? 1 : 0;
     64 if (defined $main::opt_c) {
     65     $args = "-c $main::opt_c";
     66 }
     67 elsif (defined $main::opt_p) {
     68     $args = "-p $main::opt_p";
     69 }
     70 else {
     71     usage();
     72 }
     73 
     74 #
     75 # Cleanup on signals
     76 #
     77 $SIG{INT} = \&cleanupsig;    # Ctrl-C
     78 $SIG{QUIT} = \&cleanupsig;   # Ctrl-\
     79 $SIG{TERM} = \&cleanupsig;   # TERM
     80 
     81 #
     82 # Declare DTrace script
     83 #
     84 my $dtrace = <<END;
     85 /usr/sbin/dtrace -n '
     86 	#pragma D option quiet
     87 	profile:::profile-1001hz
     88 	/pid == \$target/ 
     89 	{
     90 		\@pc[arg1] = count();
     91 	}
     92 	dtrace:::END
     93 	{
     94 		printa("OUT: %A %\@d\\n", \@pc);
     95 	}
     96 ' '$args'
     97 END
     98 
     99 #
    100 # Run DTrace, process output
    101 #
    102 my %Count;
    103 my $total;
    104 open DTRACE, "$dtrace |" or die "ERROR1: Can't run dtrace (perms?): $!\n";
    105 print "Sampling... Hit Ctrl-C to end.\n";
    106 while (my $line = <DTRACE>) {
    107     next if $line =~ /^\s*$/;
    108     next if $line !~ /^OUT: /;
    109     my ($tag, $addr, $count) = split ' ', $line;
    110     my ($name, $offset) = split /\+/, $addr;
    111     next if $name eq "0x0";
    112     $name =~ s/\`.*// if $libs;
    113     $Count{$name} += $count;
    114     $total += $count;
    115 }
    116 close DTRACE;
    117 
    118 #
    119 # Print final report
    120 #
    121 printf "\n%-52s %8s %6s\n", $libs ? "LIBRARY" : "FUNCTION", "COUNT", "PCNT";
    122 foreach my $name (sort { $Count{$a} <=> $Count{$b} } keys %Count) {
    123     printf "%-52s %8d %5.1f%%\n", $name, $Count{$name},
    124                                   100 * $Count{$name} / ($total ? $total : 1);
    125 }
    126 
    127 #
    128 # Subroutines
    129 #
    130 sub cleanupsig {
    131 }
    132 sub usage {
    133     print STDERR "USAGE: hotuser [-hl] { -c command | -p PID }\n";
    134     print STDERR "   eg,\n";
    135     print STDERR "       hotuser -p 81     # sample user funcs for PID 81\n";
    136     print STDERR "       hotuser -lp 81    # sample user libs for PID 81\n";
    137     print STDERR "       hotuser -p `pgrep -n Xorg`     # sample Xorg\n";
    138     exit 1;
    139 }
    140