1 /* hist.c - Histogram related operations.
3 Copyright 2000, 2001 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
22 #include "libiberty.h"
24 #include "search_list.h"
34 #define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
36 static void scale_and_align_entries PARAMS ((void));
38 /* Declarations of automatically generated functions to output blurbs. */
39 extern void flat_blurb PARAMS ((FILE * fp));
41 bfd_vma s_lowpc; /* Lowest address in .text. */
42 bfd_vma s_highpc = 0; /* Highest address in .text. */
43 bfd_vma lowpc, highpc; /* Same, but expressed in UNITs. */
44 int hist_num_bins = 0; /* Number of histogram samples. */
45 int *hist_sample = 0; /* Histogram samples (shorts in the file!). */
47 char hist_dimension[16] = "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). */
62 { 'T', 1e-12 }, /* tera */
63 { 'G', 1e-09 }, /* giga */
64 { 'M', 1e-06 }, /* mega */
65 { 'K', 1e-03 }, /* kilo */
67 { 'm', 1e+03 }, /* milli */
68 { 'u', 1e+06 }, /* micro */
69 { 'n', 1e+09 }, /* nano */
70 { 'p', 1e+12 }, /* pico */
71 { 'f', 1e+15 }, /* femto */
72 { 'a', 1e+18 } /* ato */
76 /* Read the histogram from file IFP. FILENAME is the name of IFP and
77 is provided for formatting error messages only. */
80 DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
82 bfd_vma n_lowpc, n_highpc;
83 int i, ncnt, profrate;
86 if (gmon_io_read_vma (ifp, &n_lowpc)
87 || gmon_io_read_vma (ifp, &n_highpc)
88 || gmon_io_read_32 (ifp, &ncnt)
89 || gmon_io_read_32 (ifp, &profrate)
90 || gmon_io_read (ifp, hist_dimension, 15)
91 || gmon_io_read (ifp, &hist_dimension_abbrev, 1))
93 fprintf (stderr, _("%s: %s: unexpected end of file\n"),
101 /* This is the first histogram record. */
104 lowpc = (bfd_vma) n_lowpc / sizeof (UNIT);
105 highpc = (bfd_vma) n_highpc / sizeof (UNIT);
106 hist_num_bins = ncnt;
111 printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n",
112 (unsigned long) n_lowpc, (unsigned long) n_highpc, ncnt);
113 printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n",
114 (unsigned long) s_lowpc, (unsigned long) s_highpc,
116 printf ("[hist_read_rec] lowpc 0x%lx highpc 0x%lx\n",
117 (unsigned long) lowpc, (unsigned long) highpc));
119 if (n_lowpc != s_lowpc || n_highpc != s_highpc
120 || ncnt != hist_num_bins || hz != profrate)
122 fprintf (stderr, _("%s: `%s' is incompatible with first gmon file\n"),
129 hist_sample = (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
130 memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
133 for (i = 0; i < hist_num_bins; ++i)
135 if (fread (&count[0], sizeof (count), 1, ifp) != 1)
138 _("%s: %s: unexpected EOF after reading %d of %d samples\n"),
139 whoami, filename, i, hist_num_bins);
142 hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
144 printf ("[hist_read_rec] 0x%lx: %u\n",
145 (unsigned long) (n_lowpc + i * (n_highpc - n_lowpc) / ncnt),
151 /* Write execution histogram to file OFP. FILENAME is the name
152 of OFP and is provided for formatting error-messages only. */
155 DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename)
162 if (gmon_io_write_8 (ofp, GMON_TAG_TIME_HIST)
163 || gmon_io_write_vma (ofp, s_lowpc)
164 || gmon_io_write_vma (ofp, s_highpc)
165 || gmon_io_write_32 (ofp, hist_num_bins)
166 || gmon_io_write_32 (ofp, hz)
167 || gmon_io_write (ofp, hist_dimension, 15)
168 || gmon_io_write (ofp, &hist_dimension_abbrev, 1))
174 for (i = 0; i < hist_num_bins; ++i)
176 bfd_put_16 (core_bfd, hist_sample[i], (bfd_byte *) & count[0]);
178 if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
187 /* Calculate scaled entry point addresses (to save time in
188 hist_assign_samples), and, on architectures that have procedure
189 entry masks at the start of a function, possibly push the scaled
190 entry points over the procedure entry mask, if it turns out that
191 the entry point is in one bin and the code for a routine is in the
195 scale_and_align_entries ()
198 bfd_vma bin_of_entry;
201 for (sym = symtab.base; sym < symtab.limit; sym++)
203 sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
204 bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale;
205 bin_of_code = ((sym->hist.scaled_addr + UNITS_TO_CODE - lowpc)
207 if (bin_of_entry < bin_of_code)
210 printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n",
211 (unsigned long) sym->hist.scaled_addr,
212 (unsigned long) (sym->hist.scaled_addr
214 sym->hist.scaled_addr += UNITS_TO_CODE;
220 /* Assign samples to the symbol to which they belong.
222 Histogram bin I covers some address range [BIN_LOWPC,BIN_HIGH_PC)
223 which may overlap one more symbol address ranges. If a symbol
224 overlaps with the bin's address range by O percent, then O percent
225 of the bin's count is credited to that symbol.
227 There are three cases as to where BIN_LOW_PC and BIN_HIGH_PC can be
228 with respect to the symbol's address range [SYM_LOW_PC,
229 SYM_HIGH_PC) as shown in the following diagram. OVERLAP computes
230 the distance (in UNITs) between the arrows, the fraction of the
231 sample that is to be credited to the symbol which starts at
234 sym_low_pc sym_high_pc
238 +-----------------------------------------------+
240 | ->| |<- ->| |<- ->| |<- |
242 +---------+ +---------+ +---------+
246 bin_low_pc bin_high_pc bin_low_pc bin_high_pc bin_low_pc bin_high_pc
248 For the VAX we assert that samples will never fall in the first two
249 bytes of any routine, since that is the entry mask, thus we call
250 scale_and_align_entries() to adjust the entry points if the entry
251 mask falls in one bin but the code for the routine doesn't start
252 until the next bin. In conjunction with the alignment of routine
253 addresses, this should allow us to have only one sample for every
254 four bytes of text space and never have any overlap (the two end
258 DEFUN_VOID (hist_assign_samples)
260 bfd_vma bin_low_pc, bin_high_pc;
261 bfd_vma sym_low_pc, sym_high_pc;
262 bfd_vma overlap, addr;
267 /* Read samples and assign to symbols. */
268 hist_scale = highpc - lowpc;
269 hist_scale /= hist_num_bins;
270 scale_and_align_entries ();
272 /* Iterate over all sample bins. */
273 for (i = 0, j = 1; i < hist_num_bins; ++i)
275 bin_count = hist_sample[i];
279 bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
280 bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
285 "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
286 (unsigned long) (sizeof (UNIT) * bin_low_pc),
287 (unsigned long) (sizeof (UNIT) * bin_high_pc),
291 /* Credit all symbols that are covered by bin I. */
292 for (j = j - 1; j < symtab.len; ++j)
294 sym_low_pc = symtab.base[j].hist.scaled_addr;
295 sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
297 /* If high end of bin is below entry address,
299 if (bin_high_pc < sym_low_pc)
302 /* If low end of bin is above high end of symbol,
303 go for next symbol. */
304 if (bin_low_pc >= sym_high_pc)
308 MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
313 "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
314 (unsigned long) symtab.base[j].addr,
315 (unsigned long) (sizeof (UNIT) * sym_high_pc),
316 symtab.base[j].name, overlap * time / hist_scale,
319 addr = symtab.base[j].addr;
320 credit = overlap * time / hist_scale;
322 /* Credit symbol if it appears in INCL_FLAT or that
323 table is empty and it does not appear it in
325 if (sym_lookup (&syms[INCL_FLAT], addr)
326 || (syms[INCL_FLAT].len == 0
327 && !sym_lookup (&syms[EXCL_FLAT], addr)))
329 symtab.base[j].hist.time += credit;
333 total_time -= credit;
339 DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
344 /* Print header for flag histogram profile. */
347 DEFUN (print_header, (prefix), const char prefix)
351 sprintf (unit, _("%c%c/call"), prefix, hist_dimension_abbrev);
353 if (bsd_style_output)
355 printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
356 (long) hist_scale * sizeof (UNIT));
357 if (total_time > 0.0)
359 printf (_(" for %.2f%% of %.2f %s\n\n"),
360 100.0 / total_time, total_time / hz, hist_dimension);
365 printf (_("\nEach sample counts as %g %s.\n"), 1.0 / hz, hist_dimension);
368 if (total_time <= 0.0)
370 printf (_(" no time accumulated\n\n"));
372 /* This doesn't hurt since all the numerators will be zero. */
376 printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
377 "% ", _("cumulative"), _("self "), "", _("self "), _("total "),
379 printf ("%5.5s %9.9s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
380 _("time"), hist_dimension, hist_dimension, _("calls"), unit, unit,
386 DEFUN (print_line, (sym, scale), Sym * sym AND double scale)
388 if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
391 accum_time += sym->hist.time;
393 if (bsd_style_output)
394 printf ("%5.1f %10.2f %8.2f",
395 total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
396 accum_time / hz, sym->hist.time / hz);
398 printf ("%6.2f %9.2f %8.2f",
399 total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
400 accum_time / hz, sym->hist.time / hz);
402 if (sym->ncalls != 0)
403 printf (" %8lu %8.2f %8.2f ",
404 sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
405 scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
407 printf (" %8.8s %8.8s %8.8s ", "", "", "");
409 if (bsd_style_output)
412 print_name_only (sym);
418 /* Compare LP and RP. The primary comparison key is execution time,
419 the secondary is number of invocation, and the tertiary is the
420 lexicographic order of the function names. */
423 DEFUN (cmp_time, (lp, rp), const PTR lp AND const PTR rp)
425 const Sym *left = *(const Sym **) lp;
426 const Sym *right = *(const Sym **) rp;
429 time_diff = right->hist.time - left->hist.time;
437 if (right->ncalls > left->ncalls)
440 if (right->ncalls < left->ncalls)
443 return strcmp (left->name, right->name);
447 /* Print the flat histogram profile. */
450 DEFUN_VOID (hist_print)
452 Sym **time_sorted_syms, *top_dog, *sym;
455 double top_time, time;
459 first_output = FALSE;
465 if (bsd_style_output)
467 if (print_descriptions)
469 printf (_("\n\n\nflat profile:\n"));
475 printf (_("Flat profile:\n"));
478 /* Sort the symbol table by time (call-count and name as secondary
479 and tertiary keys). */
480 time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
482 for (index = 0; index < symtab.len; ++index)
483 time_sorted_syms[index] = &symtab.base[index];
485 qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
487 if (bsd_style_output)
489 log_scale = 5; /* Milli-seconds is BSD-default. */
493 /* Search for symbol with highest per-call
494 execution time and scale accordingly. */
499 for (index = 0; index < symtab.len; ++index)
501 sym = time_sorted_syms[index];
503 if (sym->ncalls != 0)
505 time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
515 if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
519 while (SItab[log_scale].scale * top_time < 1000.0
520 && ((size_t) log_scale
521 < sizeof (SItab) / sizeof (SItab[0]) - 1))
528 /* For now, the dimension is always seconds. In the future, we
529 may also want to support other (pseudo-)dimensions (such as
530 I-cache misses etc.). */
531 print_header (SItab[log_scale].prefix);
533 for (index = 0; index < symtab.len; ++index)
535 addr = time_sorted_syms[index]->addr;
537 /* Print symbol if its in INCL_FLAT table or that table
538 is empty and the symbol is not in EXCL_FLAT. */
539 if (sym_lookup (&syms[INCL_FLAT], addr)
540 || (syms[INCL_FLAT].len == 0
541 && !sym_lookup (&syms[EXCL_FLAT], addr)))
542 print_line (time_sorted_syms[index], SItab[log_scale].scale);
545 free (time_sorted_syms);
547 if (print_descriptions && !bsd_style_output)