2001-01-17 Ben Elliston <bje@redhat.com>
[deliverable/binutils-gdb.git] / gprof / hist.c
CommitLineData
ef368dac
NC
1/* hist.c - Histogram related operations.
2
3 Copyright (C) 2000 Free Software Foundation, Inc.
4
5 This file is part of GNU Binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21\f
252b5132
RH
22#include <stdio.h>
23#include "libiberty.h"
24#include "gprof.h"
25#include "corefile.h"
26#include "gmon_io.h"
27#include "gmon_out.h"
28#include "hist.h"
29#include "symtab.h"
30#include "sym_ids.h"
31#include "utils.h"
32
33#define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
34
35static void scale_and_align_entries PARAMS ((void));
36
ef368dac 37/* Declarations of automatically generated functions to output blurbs. */
252b5132
RH
38extern void flat_blurb PARAMS ((FILE * fp));
39
ef368dac
NC
40bfd_vma s_lowpc; /* Lowest address in .text. */
41bfd_vma s_highpc = 0; /* Highest address in .text. */
42bfd_vma lowpc, highpc; /* Same, but expressed in UNITs. */
43int hist_num_bins = 0; /* Number of histogram samples. */
44int *hist_sample = 0; /* Histogram samples (shorts in the file!). */
252b5132
RH
45double hist_scale;
46char hist_dimension[sizeof (((struct gmon_hist_hdr *) 0)->dimen) + 1] =
47 "seconds";
48char hist_dimension_abbrev = 's';
49
ef368dac
NC
50static double accum_time; /* Accumulated time so far for print_line(). */
51static double total_time; /* Total time for all routines. */
52
53/* Table of SI prefixes for powers of 10 (used to automatically
54 scale some of the values in the flat profile). */
252b5132
RH
55const struct
56 {
57 char prefix;
58 double scale;
59 }
60SItab[] =
61{
62 {
63 'T', 1e-12
64 }
65 , /* tera */
66 {
67 'G', 1e-09
68 }
69 , /* giga */
70 {
71 'M', 1e-06
72 }
73 , /* mega */
74 {
75 'K', 1e-03
76 }
77 , /* kilo */
78 {
79 ' ', 1e-00
80 }
81 ,
82 {
83 'm', 1e+03
84 }
85 , /* milli */
86 {
87 'u', 1e+06
88 }
89 , /* micro */
90 {
91 'n', 1e+09
92 }
93 , /* nano */
94 {
95 'p', 1e+12
96 }
97 , /* pico */
98 {
99 'f', 1e+15
100 }
101 , /* femto */
102 {
103 'a', 1e+18
104 }
105 , /* ato */
106};
107
ef368dac
NC
108
109/* Read the histogram from file IFP. FILENAME is the name of IFP and
110 is provided for formatting error messages only. */
111
252b5132
RH
112void
113DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
114{
115 struct gmon_hist_hdr hdr;
116 bfd_vma n_lowpc, n_highpc;
117 int i, ncnt, profrate;
118 UNIT count;
119
120 if (fread (&hdr, sizeof (hdr), 1, ifp) != 1)
121 {
122 fprintf (stderr, _("%s: %s: unexpected end of file\n"),
123 whoami, filename);
124 done (1);
125 }
126
127 n_lowpc = (bfd_vma) get_vma (core_bfd, (bfd_byte *) hdr.low_pc);
128 n_highpc = (bfd_vma) get_vma (core_bfd, (bfd_byte *) hdr.high_pc);
129 ncnt = bfd_get_32 (core_bfd, (bfd_byte *) hdr.hist_size);
130 profrate = bfd_get_32 (core_bfd, (bfd_byte *) hdr.prof_rate);
131 strncpy (hist_dimension, hdr.dimen, sizeof (hdr.dimen));
132 hist_dimension[sizeof (hdr.dimen)] = '\0';
133 hist_dimension_abbrev = hdr.dimen_abbrev;
134
135 if (!s_highpc)
136 {
ef368dac 137 /* This is the first histogram record. */
252b5132
RH
138 s_lowpc = n_lowpc;
139 s_highpc = n_highpc;
140 lowpc = (bfd_vma) n_lowpc / sizeof (UNIT);
141 highpc = (bfd_vma) n_highpc / sizeof (UNIT);
142 hist_num_bins = ncnt;
143 hz = profrate;
144 }
145
146 DBG (SAMPLEDEBUG,
147 printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n",
fdcf7d43 148 (unsigned long) n_lowpc, (unsigned long) n_highpc, ncnt);
252b5132 149 printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n",
fdcf7d43
ILT
150 (unsigned long) s_lowpc, (unsigned long) s_highpc,
151 hist_num_bins);
252b5132 152 printf ("[hist_read_rec] lowpc 0x%lx highpc 0x%lx\n",
fdcf7d43 153 (unsigned long) lowpc, (unsigned long) highpc));
252b5132
RH
154
155 if (n_lowpc != s_lowpc || n_highpc != s_highpc
156 || ncnt != hist_num_bins || hz != profrate)
157 {
158 fprintf (stderr, _("%s: `%s' is incompatible with first gmon file\n"),
159 whoami, filename);
160 done (1);
161 }
162
163 if (!hist_sample)
164 {
165 hist_sample = (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
166 memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
167 }
168
169 for (i = 0; i < hist_num_bins; ++i)
170 {
171 if (fread (&count[0], sizeof (count), 1, ifp) != 1)
172 {
173 fprintf (stderr,
174 _("%s: %s: unexpected EOF after reading %d of %d samples\n"),
175 whoami, filename, i, hist_num_bins);
176 done (1);
177 }
178 hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
179 }
180}
181
182
ef368dac
NC
183/* Write execution histogram to file OFP. FILENAME is the name
184 of OFP and is provided for formatting error-messages only. */
185
252b5132
RH
186void
187DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename)
188{
189 struct gmon_hist_hdr hdr;
190 unsigned char tag;
191 UNIT count;
192 int i;
193
ef368dac 194 /* Write header. */
252b5132
RH
195
196 tag = GMON_TAG_TIME_HIST;
197 put_vma (core_bfd, s_lowpc, (bfd_byte *) hdr.low_pc);
198 put_vma (core_bfd, s_highpc, (bfd_byte *) hdr.high_pc);
199 bfd_put_32 (core_bfd, hist_num_bins, (bfd_byte *) hdr.hist_size);
200 bfd_put_32 (core_bfd, hz, (bfd_byte *) hdr.prof_rate);
201 strncpy (hdr.dimen, hist_dimension, sizeof (hdr.dimen));
202 hdr.dimen_abbrev = hist_dimension_abbrev;
203
204 if (fwrite (&tag, sizeof (tag), 1, ofp) != 1
205 || fwrite (&hdr, sizeof (hdr), 1, ofp) != 1)
206 {
207 perror (filename);
208 done (1);
209 }
210
211 for (i = 0; i < hist_num_bins; ++i)
212 {
213 bfd_put_16 (core_bfd, hist_sample[i], (bfd_byte *) & count[0]);
ef368dac 214
252b5132
RH
215 if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
216 {
217 perror (filename);
218 done (1);
219 }
220 }
221}
222
223
ef368dac
NC
224/* Calculate scaled entry point addresses (to save time in
225 hist_assign_samples), and, on architectures that have procedure
226 entry masks at the start of a function, possibly push the scaled
227 entry points over the procedure entry mask, if it turns out that
228 the entry point is in one bin and the code for a routine is in the
229 next bin. */
230
252b5132
RH
231static void
232scale_and_align_entries ()
233{
234 Sym *sym;
235 bfd_vma bin_of_entry;
236 bfd_vma bin_of_code;
237
238 for (sym = symtab.base; sym < symtab.limit; sym++)
239 {
240 sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
241 bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale;
242 bin_of_code = (sym->hist.scaled_addr + UNITS_TO_CODE - lowpc) / hist_scale;
243 if (bin_of_entry < bin_of_code)
244 {
245 DBG (SAMPLEDEBUG,
246 printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n",
fdcf7d43
ILT
247 (unsigned long) sym->hist.scaled_addr,
248 (unsigned long) (sym->hist.scaled_addr
249 + UNITS_TO_CODE)));
252b5132
RH
250 sym->hist.scaled_addr += UNITS_TO_CODE;
251 }
252 }
253}
254
255
ef368dac
NC
256/* Assign samples to the symbol to which they belong.
257
258 Histogram bin I covers some address range [BIN_LOWPC,BIN_HIGH_PC)
259 which may overlap one more symbol address ranges. If a symbol
260 overlaps with the bin's address range by O percent, then O percent
261 of the bin's count is credited to that symbol.
262
263 There are three cases as to where BIN_LOW_PC and BIN_HIGH_PC can be
264 with respect to the symbol's address range [SYM_LOW_PC,
265 SYM_HIGH_PC) as shown in the following diagram. OVERLAP computes
266 the distance (in UNITs) between the arrows, the fraction of the
267 sample that is to be credited to the symbol which starts at
268 SYM_LOW_PC.
269
270 sym_low_pc sym_high_pc
271 | |
272 v v
273
274 +-----------------------------------------------+
275 | |
276 | ->| |<- ->| |<- ->| |<- |
277 | | | | | |
278 +---------+ +---------+ +---------+
279
280 ^ ^ ^ ^ ^ ^
281 | | | | | |
282 bin_low_pc bin_high_pc bin_low_pc bin_high_pc bin_low_pc bin_high_pc
283
284 For the VAX we assert that samples will never fall in the first two
285 bytes of any routine, since that is the entry mask, thus we call
286 scale_and_align_entries() to adjust the entry points if the entry
287 mask falls in one bin but the code for the routine doesn't start
288 until the next bin. In conjunction with the alignment of routine
289 addresses, this should allow us to have only one sample for every
290 four bytes of text space and never have any overlap (the two end
291 cases, above). */
292
252b5132
RH
293void
294DEFUN_VOID (hist_assign_samples)
295{
296 bfd_vma bin_low_pc, bin_high_pc;
297 bfd_vma sym_low_pc, sym_high_pc;
298 bfd_vma overlap, addr;
299 int bin_count, i;
300 unsigned int j;
301 double time, credit;
302
ef368dac 303 /* Read samples and assign to symbols. */
252b5132
RH
304 hist_scale = highpc - lowpc;
305 hist_scale /= hist_num_bins;
306 scale_and_align_entries ();
307
ef368dac 308 /* Iterate over all sample bins. */
252b5132
RH
309 for (i = 0, j = 1; i < hist_num_bins; ++i)
310 {
311 bin_count = hist_sample[i];
ef368dac
NC
312 if (! bin_count)
313 continue;
314
252b5132
RH
315 bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
316 bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
317 time = bin_count;
ef368dac 318
252b5132
RH
319 DBG (SAMPLEDEBUG,
320 printf (
321 "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
fdcf7d43
ILT
322 (unsigned long) (sizeof (UNIT) * bin_low_pc),
323 (unsigned long) (sizeof (UNIT) * bin_high_pc),
252b5132
RH
324 bin_count));
325 total_time += time;
326
ef368dac 327 /* Credit all symbols that are covered by bin I. */
252b5132
RH
328 for (j = j - 1; j < symtab.len; ++j)
329 {
330 sym_low_pc = symtab.base[j].hist.scaled_addr;
331 sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
ef368dac
NC
332
333 /* If high end of bin is below entry address,
334 go for next bin. */
252b5132 335 if (bin_high_pc < sym_low_pc)
ef368dac
NC
336 break;
337
338 /* If low end of bin is above high end of symbol,
339 go for next symbol. */
252b5132 340 if (bin_low_pc >= sym_high_pc)
ef368dac
NC
341 continue;
342
252b5132
RH
343 overlap =
344 MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
345 if (overlap > 0)
346 {
347 DBG (SAMPLEDEBUG,
348 printf (
349 "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
fdcf7d43
ILT
350 (unsigned long) symtab.base[j].addr,
351 (unsigned long) (sizeof (UNIT) * sym_high_pc),
252b5132 352 symtab.base[j].name, overlap * time / hist_scale,
fdcf7d43 353 (long) overlap));
ef368dac 354
252b5132
RH
355 addr = symtab.base[j].addr;
356 credit = overlap * time / hist_scale;
ef368dac
NC
357
358 /* Credit symbol if it appears in INCL_FLAT or that
359 table is empty and it does not appear it in
360 EXCL_FLAT. */
252b5132
RH
361 if (sym_lookup (&syms[INCL_FLAT], addr)
362 || (syms[INCL_FLAT].len == 0
363 && !sym_lookup (&syms[EXCL_FLAT], addr)))
364 {
365 symtab.base[j].hist.time += credit;
366 }
367 else
368 {
369 total_time -= credit;
370 }
371 }
372 }
373 }
ef368dac 374
252b5132
RH
375 DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
376 total_time));
377}
378
379
ef368dac
NC
380/* Print header for flag histogram profile. */
381
252b5132
RH
382static void
383DEFUN (print_header, (prefix), const char prefix)
384{
385 char unit[64];
386
387 sprintf (unit, _("%c%c/call"), prefix, hist_dimension_abbrev);
388
389 if (bsd_style_output)
390 {
391 printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
392 (long) hist_scale * sizeof (UNIT));
393 if (total_time > 0.0)
394 {
395 printf (_(" for %.2f%% of %.2f %s\n\n"),
396 100.0 / total_time, total_time / hz, hist_dimension);
397 }
398 }
399 else
400 {
401 printf (_("\nEach sample counts as %g %s.\n"), 1.0 / hz, hist_dimension);
402 }
403
404 if (total_time <= 0.0)
405 {
406 printf (_(" no time accumulated\n\n"));
ef368dac
NC
407
408 /* This doesn't hurt since all the numerators will be zero. */
252b5132
RH
409 total_time = 1.0;
410 }
411
412 printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
413 "% ", _("cumulative"), _("self "), "", _("self "), _("total "), "");
414 printf ("%5.5s %9.9s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
415 _("time"), hist_dimension, hist_dimension, _("calls"), unit, unit,
416 _("name"));
417}
418
419
420static void
421DEFUN (print_line, (sym, scale), Sym * sym AND double scale)
422{
423 if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
ef368dac 424 return;
252b5132
RH
425
426 accum_time += sym->hist.time;
ef368dac 427
252b5132 428 if (bsd_style_output)
ef368dac
NC
429 printf ("%5.1f %10.2f %8.2f",
430 total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
431 accum_time / hz, sym->hist.time / hz);
252b5132 432 else
ef368dac
NC
433 printf ("%6.2f %9.2f %8.2f",
434 total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
435 accum_time / hz, sym->hist.time / hz);
436
252b5132 437 if (sym->ncalls != 0)
ef368dac
NC
438 printf (" %8lu %8.2f %8.2f ",
439 sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
440 scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
252b5132 441 else
ef368dac
NC
442 printf (" %8.8s %8.8s %8.8s ", "", "", "");
443
252b5132 444 if (bsd_style_output)
ef368dac 445 print_name (sym);
252b5132 446 else
ef368dac
NC
447 print_name_only (sym);
448
252b5132
RH
449 printf ("\n");
450}
451
452
ef368dac
NC
453/* Compare LP and RP. The primary comparison key is execution time,
454 the secondary is number of invocation, and the tertiary is the
455 lexicographic order of the function names. */
456
252b5132
RH
457static int
458DEFUN (cmp_time, (lp, rp), const PTR lp AND const PTR rp)
459{
460 const Sym *left = *(const Sym **) lp;
461 const Sym *right = *(const Sym **) rp;
462 double time_diff;
463
464 time_diff = right->hist.time - left->hist.time;
ef368dac 465
252b5132 466 if (time_diff > 0.0)
ef368dac
NC
467 return 1;
468
252b5132 469 if (time_diff < 0.0)
ef368dac 470 return -1;
252b5132
RH
471
472 if (right->ncalls > left->ncalls)
ef368dac
NC
473 return 1;
474
252b5132 475 if (right->ncalls < left->ncalls)
ef368dac 476 return -1;
252b5132
RH
477
478 return strcmp (left->name, right->name);
479}
480
481
ef368dac
NC
482/* Print the flat histogram profile. */
483
252b5132
RH
484void
485DEFUN_VOID (hist_print)
486{
487 Sym **time_sorted_syms, *top_dog, *sym;
488 unsigned int index;
489 int log_scale;
490 double top_time, time;
491 bfd_vma addr;
492
493 if (first_output)
ef368dac 494 first_output = FALSE;
252b5132 495 else
ef368dac 496 printf ("\f\n");
252b5132
RH
497
498 accum_time = 0.0;
ef368dac 499
252b5132
RH
500 if (bsd_style_output)
501 {
502 if (print_descriptions)
503 {
504 printf (_("\n\n\nflat profile:\n"));
505 flat_blurb (stdout);
506 }
507 }
508 else
509 {
510 printf (_("Flat profile:\n"));
511 }
ef368dac
NC
512
513 /* Sort the symbol table by time (call-count and name as secondary
514 and tertiary keys). */
252b5132 515 time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
ef368dac 516
252b5132 517 for (index = 0; index < symtab.len; ++index)
ef368dac
NC
518 time_sorted_syms[index] = &symtab.base[index];
519
252b5132
RH
520 qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
521
522 if (bsd_style_output)
523 {
ef368dac 524 log_scale = 5; /* Milli-seconds is BSD-default. */
252b5132
RH
525 }
526 else
527 {
ef368dac
NC
528 /* Search for symbol with highest per-call
529 execution time and scale accordingly. */
252b5132
RH
530 log_scale = 0;
531 top_dog = 0;
532 top_time = 0.0;
ef368dac 533
252b5132
RH
534 for (index = 0; index < symtab.len; ++index)
535 {
536 sym = time_sorted_syms[index];
ef368dac 537
252b5132
RH
538 if (sym->ncalls != 0)
539 {
540 time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
ef368dac 541
252b5132
RH
542 if (time > top_time)
543 {
544 top_dog = sym;
545 top_time = time;
546 }
547 }
548 }
ef368dac 549
252b5132
RH
550 if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
551 {
552 top_time /= hz;
ef368dac 553
252b5132
RH
554 while (SItab[log_scale].scale * top_time < 1000.0
555 && ((size_t) log_scale
556 < sizeof (SItab) / sizeof (SItab[0]) - 1))
557 {
558 ++log_scale;
559 }
560 }
561 }
562
ef368dac
NC
563 /* For now, the dimension is always seconds. In the future, we
564 may also want to support other (pseudo-)dimensions (such as
565 I-cache misses etc.). */
252b5132 566 print_header (SItab[log_scale].prefix);
ef368dac 567
252b5132
RH
568 for (index = 0; index < symtab.len; ++index)
569 {
570 addr = time_sorted_syms[index]->addr;
ef368dac
NC
571
572 /* Print symbol if its in INCL_FLAT table or that table
573 is empty and the symbol is not in EXCL_FLAT. */
252b5132
RH
574 if (sym_lookup (&syms[INCL_FLAT], addr)
575 || (syms[INCL_FLAT].len == 0
576 && !sym_lookup (&syms[EXCL_FLAT], addr)))
ef368dac 577 print_line (time_sorted_syms[index], SItab[log_scale].scale);
252b5132 578 }
ef368dac 579
252b5132
RH
580 free (time_sorted_syms);
581
582 if (print_descriptions && !bsd_style_output)
ef368dac 583 flat_blurb (stdout);
252b5132 584}
This page took 0.082032 seconds and 4 git commands to generate.