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