5 # Analyzes the output files created by the profile command for
9 # 14 Aug, 2006 Created (Rogier Meurs)
12 $UNSIGNED_MAX_DIV_K = 2**32/1000;
15 if ($#ARGV == 0 || process_args
(@ARGV)) {
17 print " cprofalyze.pl <clock> [-f] [-aoct] [-i] [-n number] file ...\n\n";
18 print " clock CPU clock of source machine in MHz (mandatory)\n";
19 print " -f print totals per function (original order lost)\n";
20 print " -a sort alphabetically (default)\n";
21 print " -o no sort (original order)\n";
22 print " -c sort by number of calls\n";
23 print " -t sort by time spent\n";
24 print " -n print maximum of number lines per process\n";
25 print " -i when -[ao] used: print full paths\n";
33 return 1 unless /^(\d+)$/;
38 while (@_[0] =~ /^-/) {
41 if (/^-a$/) { $sort_method = "A"; last SWITCH
; }
42 if (/^-o$/) { $sort_method = "O"; last SWITCH
; }
43 if (/^-c$/) { $sort_method = "C"; last SWITCH
; }
44 if (/^-t$/) { $sort_method = "T"; last SWITCH
; }
45 if (/^-i$/) { $print_full_paths = 1; last SWITCH
; }
46 if (/^-f$/) { $print_totals = 1; last SWITCH
; }
49 return 1 unless /^(\d+)$/;
50 return 1 unless $1 > 0;
58 $print_full_paths == 1 && ($sort_method eq "T" || $sort_method eq "C") &&
59 { $print_full_paths = 0 };
68 - Calls attributed to a path are calls done on that call level.
69 For instance: a() is called once and calls b() twice. Call path "a" is
70 attributed 1 call, call path "a b" is attributed 2 calls.
71 - Time spent blocking is included.
72 - Time attributed to a path is time spent on that call level.
73 For instance: a() spends 10 cycles in its own body and calls b() which
74 spends 5 cycles in its body. Call path "a" is attributed 10 cycles,
75 call path "a b" is attributed 5 cycles.
76 - Time is attributed when a function exits. Functions calls that have not
77 returned yet are therefore not measured. This is most notable in main
78 functions that are printed as having zero cycles.
79 - When "profile reset" was run, the actual resetting in a process happens
80 when a function is entered. In some processes (for example, blocking
81 ones) this may not happen immediately, or at all.
85 print "Clockspeed entered: $MHz MHz. ";
87 if ($sort_method eq "A")
88 { print "Sorting alphabetically. "; last SWITCH
; }
89 if ($sort_method eq "C")
90 { print "Sorting by calls. "; last SWITCH
; }
91 if ($sort_method eq "T")
92 { print "Sorting by time spent. "; last SWITCH
; }
93 print "No sorting applied. ";
96 $print_totals and print "Printing totals per function. ";
97 $show_paths == 0 ?
print "Printing all call paths.\n" :
98 print "Printing max. $show_paths lines per process.\n";
100 foreach $file (@files) {
101 $file_res = read_file
($file);
102 next if $file_res == 0;
103 print_file
($print_totals ? make_totals
($file_res) : $file_res);
114 my $exe_name, $slots_used, $buf, $lo, $hi, $cycles_div_k, $ms;
116 unless (open(FILE
, $file)) {
117 print "\nERROR: Unable to open $file: $!\n";
121 $file =~ s/^.*\///; # basename
123 # First line: check file type.
127 print "Statistical Profiling output file: ";
128 print "Use sprofalyze.pl instead.\n";
130 print "Not a profiling output file.\n";
135 # Second line: header with call path string size.
137 ($CPATH_MAX_LEN, $PROCNAME_LEN) = split(/ /);
138 $SLOT_SIZE = $CPATH_MAX_LEN + 16;
139 $EXE_HEADER_SIZE = $PROCNAME_LEN + 4;
141 # Read in the data for all the processes and put it in a hash of lists.
142 # A list for each process, which contains lists itself for each call
145 read(FILE
, $buf, $EXE_HEADER_SIZE) == $EXE_HEADER_SIZE or
147 ($exe_name, $slots_used) = unpack("Z${PROCNAME_LEN}i", $buf);
150 for ($i=0; $i<$slots_used; $i++) {
151 read(FILE
, $buf, $SLOT_SIZE) == $SLOT_SIZE or
153 ($chain, $cpath, $calls, $lo, $hi) =
154 unpack("iA${CPATH_MAX_LEN}iII", $buf);
156 $cycles_div_k = $hi * $UNSIGNED_MAX_DIV_K;
157 $cycles_div_k += $lo / 1000;
158 $ms = $cycles_div_k / $MHz;
160 push @exe, [ ($cpath, $calls, $ms) ];
162 $file_res{$exe_name} = [ @exe ];
168 # Aggregate calls and cycles of paths into totals for each function.
172 my %file_res = %{$ref};
174 my %res, %calls, %time;
177 foreach $exe (sort keys %file_res) {
181 @ar = @
{$file_res{$exe}};
182 foreach $path (@ar) {
184 s/^.* //; # basename of call path
185 $calls{$_} += $path->[1];
186 $time{$_} += $path->[2];
188 foreach $func (keys %calls) {
189 push @totals, [ ($func, $calls{$func}, $time{$func}) ];
191 $res{$exe} = [ @totals ];
200 my %file_res = %{$ref};
203 printf "\n========================================";
204 printf "========================================\n";
205 printf("Data file: %s\n", $file);
206 printf "========================================";
207 printf "========================================\n\n";
209 # If we have the kernel, print it first. Then the others.
210 print_exe
($file_res{"kernel"}, "kernel") if exists($file_res{"kernel"});
212 foreach $exe (sort keys %file_res) {
213 print_exe
($file_res{$exe}, $exe) unless $exe eq "kernel";
223 my @funcs, @oldfuncs;
225 my $slots_used = @exe;
228 printf "----------------------------------------";
229 printf "----------------------------------------\n";
230 $print_totals ?
printf "%-8s %60s functions\n", $name, $slots_used :
231 printf "%-8s %59s call paths\n", $name, $slots_used;
232 printf "----------------------------------------";
233 printf "----------------------------------------\n";
234 printf("%10s %12s path\n", "calls", "msecs");
235 printf "----------------------------------------";
236 printf "----------------------------------------\n";
239 if ($sort_method eq "A") {
240 @exe = sort { lc($a->[0]) cmp lc($b->[0]) } @exe; last SWITCH
; }
241 if ($sort_method eq "C") {
242 @exe = reverse sort { $a->[1] <=> $b->[1] } @exe; last SWITCH
; }
243 if ($sort_method eq "T") {
244 @exe = reverse sort { $a->[2] <=> $b->[2] } @exe; last SWITCH
; }
250 foreach $path (@exe) {
251 printf("%10u %12.2f ", $path->[1], $path->[2]);
253 if ($print_full_paths == 1 ||
254 ($sort_method eq "C" || $sort_method eq "T")) {
257 @funcs = split(/ /, $path->[0]);
258 for (my $j=0; $j<=$#funcs; $j++) {
259 if ($j<=$#oldfuncs && $funcs[$j] eq $oldfuncs[$j]) {
262 print " " if ($j > 0);
269 last if (++$paths == $show_paths);