2001-05-28 Philip Blundell <philb@gnu.org>
[binutils.git] / gprof / hist.c
bloba4cb1a40bd9508083d07da50aeea15e5323d070d
1 /* hist.c - Histogram related operations.
3 Copyright (C) 2000 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
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.
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.
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. */
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"
33 #define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
35 static void scale_and_align_entries PARAMS ((void));
37 /* Declarations of automatically generated functions to output blurbs. */
38 extern void flat_blurb PARAMS ((FILE * fp));
40 bfd_vma s_lowpc; /* Lowest address in .text. */
41 bfd_vma s_highpc = 0; /* Highest address in .text. */
42 bfd_vma lowpc, highpc; /* Same, but expressed in UNITs. */
43 int hist_num_bins = 0; /* Number of histogram samples. */
44 int *hist_sample = 0; /* Histogram samples (shorts in the file!). */
45 double hist_scale;
46 char hist_dimension[sizeof (((struct gmon_hist_hdr *) 0)->dimen) + 1] =
47 "seconds";
48 char hist_dimension_abbrev = 's';
50 static double accum_time; /* Accumulated time so far for print_line(). */
51 static double total_time; /* Total time for all routines. */
53 /* Table of SI prefixes for powers of 10 (used to automatically
54 scale some of the values in the flat profile). */
55 const struct
57 char prefix;
58 double scale;
60 SItab[] =
63 'T', 1e-12
65 , /* tera */
67 'G', 1e-09
69 , /* giga */
71 'M', 1e-06
73 , /* mega */
75 'K', 1e-03
77 , /* kilo */
79 ' ', 1e-00
83 'm', 1e+03
85 , /* milli */
87 'u', 1e+06
89 , /* micro */
91 'n', 1e+09
93 , /* nano */
95 'p', 1e+12
97 , /* pico */
99 'f', 1e+15
101 , /* femto */
103 'a', 1e+18
105 , /* ato */
109 /* Read the histogram from file IFP. FILENAME is the name of IFP and
110 is provided for formatting error messages only. */
112 void
113 DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
115 struct gmon_hist_hdr hdr;
116 bfd_vma n_lowpc, n_highpc;
117 int i, ncnt, profrate;
118 UNIT count;
120 if (fread (&hdr, sizeof (hdr), 1, ifp) != 1)
122 fprintf (stderr, _("%s: %s: unexpected end of file\n"),
123 whoami, filename);
124 done (1);
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;
135 if (!s_highpc)
137 /* This is the first histogram record. */
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;
146 DBG (SAMPLEDEBUG,
147 printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n",
148 (unsigned long) n_lowpc, (unsigned long) n_highpc, ncnt);
149 printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n",
150 (unsigned long) s_lowpc, (unsigned long) s_highpc,
151 hist_num_bins);
152 printf ("[hist_read_rec] lowpc 0x%lx highpc 0x%lx\n",
153 (unsigned long) lowpc, (unsigned long) highpc));
155 if (n_lowpc != s_lowpc || n_highpc != s_highpc
156 || ncnt != hist_num_bins || hz != profrate)
158 fprintf (stderr, _("%s: `%s' is incompatible with first gmon file\n"),
159 whoami, filename);
160 done (1);
163 if (!hist_sample)
165 hist_sample = (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
166 memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
169 for (i = 0; i < hist_num_bins; ++i)
171 if (fread (&count[0], sizeof (count), 1, ifp) != 1)
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);
178 hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
183 /* Write execution histogram to file OFP. FILENAME is the name
184 of OFP and is provided for formatting error-messages only. */
186 void
187 DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename)
189 struct gmon_hist_hdr hdr;
190 unsigned char tag;
191 UNIT count;
192 int i;
194 /* Write header. */
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;
204 if (fwrite (&tag, sizeof (tag), 1, ofp) != 1
205 || fwrite (&hdr, sizeof (hdr), 1, ofp) != 1)
207 perror (filename);
208 done (1);
211 for (i = 0; i < hist_num_bins; ++i)
213 bfd_put_16 (core_bfd, hist_sample[i], (bfd_byte *) & count[0]);
215 if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
217 perror (filename);
218 done (1);
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. */
231 static void
232 scale_and_align_entries ()
234 Sym *sym;
235 bfd_vma bin_of_entry;
236 bfd_vma bin_of_code;
238 for (sym = symtab.base; sym < symtab.limit; sym++)
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)
245 DBG (SAMPLEDEBUG,
246 printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n",
247 (unsigned long) sym->hist.scaled_addr,
248 (unsigned long) (sym->hist.scaled_addr
249 + UNITS_TO_CODE)));
250 sym->hist.scaled_addr += UNITS_TO_CODE;
256 /* Assign samples to the symbol to which they belong.
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.
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.
270 sym_low_pc sym_high_pc
274 +-----------------------------------------------+
276 | ->| |<- ->| |<- ->| |<- |
277 | | | | | |
278 +---------+ +---------+ +---------+
280 ^ ^ ^ ^ ^ ^
281 | | | | | |
282 bin_low_pc bin_high_pc bin_low_pc bin_high_pc bin_low_pc bin_high_pc
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). */
293 void
294 DEFUN_VOID (hist_assign_samples)
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;
303 /* Read samples and assign to symbols. */
304 hist_scale = highpc - lowpc;
305 hist_scale /= hist_num_bins;
306 scale_and_align_entries ();
308 /* Iterate over all sample bins. */
309 for (i = 0, j = 1; i < hist_num_bins; ++i)
311 bin_count = hist_sample[i];
312 if (! bin_count)
313 continue;
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;
319 DBG (SAMPLEDEBUG,
320 printf (
321 "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
322 (unsigned long) (sizeof (UNIT) * bin_low_pc),
323 (unsigned long) (sizeof (UNIT) * bin_high_pc),
324 bin_count));
325 total_time += time;
327 /* Credit all symbols that are covered by bin I. */
328 for (j = j - 1; j < symtab.len; ++j)
330 sym_low_pc = symtab.base[j].hist.scaled_addr;
331 sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
333 /* If high end of bin is below entry address,
334 go for next bin. */
335 if (bin_high_pc < sym_low_pc)
336 break;
338 /* If low end of bin is above high end of symbol,
339 go for next symbol. */
340 if (bin_low_pc >= sym_high_pc)
341 continue;
343 overlap =
344 MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
345 if (overlap > 0)
347 DBG (SAMPLEDEBUG,
348 printf (
349 "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
350 (unsigned long) symtab.base[j].addr,
351 (unsigned long) (sizeof (UNIT) * sym_high_pc),
352 symtab.base[j].name, overlap * time / hist_scale,
353 (long) overlap));
355 addr = symtab.base[j].addr;
356 credit = overlap * time / hist_scale;
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. */
361 if (sym_lookup (&syms[INCL_FLAT], addr)
362 || (syms[INCL_FLAT].len == 0
363 && !sym_lookup (&syms[EXCL_FLAT], addr)))
365 symtab.base[j].hist.time += credit;
367 else
369 total_time -= credit;
375 DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
376 total_time));
380 /* Print header for flag histogram profile. */
382 static void
383 DEFUN (print_header, (prefix), const char prefix)
385 char unit[64];
387 sprintf (unit, _("%c%c/call"), prefix, hist_dimension_abbrev);
389 if (bsd_style_output)
391 printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
392 (long) hist_scale * sizeof (UNIT));
393 if (total_time > 0.0)
395 printf (_(" for %.2f%% of %.2f %s\n\n"),
396 100.0 / total_time, total_time / hz, hist_dimension);
399 else
401 printf (_("\nEach sample counts as %g %s.\n"), 1.0 / hz, hist_dimension);
404 if (total_time <= 0.0)
406 printf (_(" no time accumulated\n\n"));
408 /* This doesn't hurt since all the numerators will be zero. */
409 total_time = 1.0;
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"));
420 static void
421 DEFUN (print_line, (sym, scale), Sym * sym AND double scale)
423 if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
424 return;
426 accum_time += sym->hist.time;
428 if (bsd_style_output)
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);
432 else
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);
437 if (sym->ncalls != 0)
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);
441 else
442 printf (" %8.8s %8.8s %8.8s ", "", "", "");
444 if (bsd_style_output)
445 print_name (sym);
446 else
447 print_name_only (sym);
449 printf ("\n");
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. */
457 static int
458 DEFUN (cmp_time, (lp, rp), const PTR lp AND const PTR rp)
460 const Sym *left = *(const Sym **) lp;
461 const Sym *right = *(const Sym **) rp;
462 double time_diff;
464 time_diff = right->hist.time - left->hist.time;
466 if (time_diff > 0.0)
467 return 1;
469 if (time_diff < 0.0)
470 return -1;
472 if (right->ncalls > left->ncalls)
473 return 1;
475 if (right->ncalls < left->ncalls)
476 return -1;
478 return strcmp (left->name, right->name);
482 /* Print the flat histogram profile. */
484 void
485 DEFUN_VOID (hist_print)
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;
493 if (first_output)
494 first_output = FALSE;
495 else
496 printf ("\f\n");
498 accum_time = 0.0;
500 if (bsd_style_output)
502 if (print_descriptions)
504 printf (_("\n\n\nflat profile:\n"));
505 flat_blurb (stdout);
508 else
510 printf (_("Flat profile:\n"));
513 /* Sort the symbol table by time (call-count and name as secondary
514 and tertiary keys). */
515 time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
517 for (index = 0; index < symtab.len; ++index)
518 time_sorted_syms[index] = &symtab.base[index];
520 qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
522 if (bsd_style_output)
524 log_scale = 5; /* Milli-seconds is BSD-default. */
526 else
528 /* Search for symbol with highest per-call
529 execution time and scale accordingly. */
530 log_scale = 0;
531 top_dog = 0;
532 top_time = 0.0;
534 for (index = 0; index < symtab.len; ++index)
536 sym = time_sorted_syms[index];
538 if (sym->ncalls != 0)
540 time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
542 if (time > top_time)
544 top_dog = sym;
545 top_time = time;
550 if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
552 top_time /= hz;
554 while (SItab[log_scale].scale * top_time < 1000.0
555 && ((size_t) log_scale
556 < sizeof (SItab) / sizeof (SItab[0]) - 1))
558 ++log_scale;
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.). */
566 print_header (SItab[log_scale].prefix);
568 for (index = 0; index < symtab.len; ++index)
570 addr = time_sorted_syms[index]->addr;
572 /* Print symbol if its in INCL_FLAT table or that table
573 is empty and the symbol is not in EXCL_FLAT. */
574 if (sym_lookup (&syms[INCL_FLAT], addr)
575 || (syms[INCL_FLAT].len == 0
576 && !sym_lookup (&syms[EXCL_FLAT], addr)))
577 print_line (time_sorted_syms[index], SItab[log_scale].scale);
580 free (time_sorted_syms);
582 if (print_descriptions && !bsd_style_output)
583 flat_blurb (stdout);