]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - cddl/contrib/dtracetoolkit/hotuser
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / cddl / contrib / dtracetoolkit / hotuser
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 65 2007-10-04 11:09:40Z brendan $
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 }