2 * Histogram related operations.
15 #define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
17 static void scale_and_align_entries
PARAMS ((void));
19 /* declarations of automatically generated functions to output blurbs: */
20 extern void flat_blurb
PARAMS ((FILE * fp
));
22 bfd_vma s_lowpc
; /* lowest address in .text */
23 bfd_vma s_highpc
= 0; /* highest address in .text */
24 bfd_vma lowpc
, highpc
; /* same, but expressed in UNITs */
25 int hist_num_bins
= 0; /* number of histogram samples */
26 int *hist_sample
= 0; /* histogram samples (shorts in the file!) */
28 char hist_dimension
[sizeof (((struct gmon_hist_hdr
*) 0)->dimen
) + 1] =
30 char hist_dimension_abbrev
= 's';
32 static double accum_time
; /* accumulated time so far for print_line() */
33 static double total_time
; /* total time for all routines */
35 * Table of SI prefixes for powers of 10 (used to automatically
36 * scale some of the values in the flat profile).
92 * Read the histogram from file IFP. FILENAME is the name of IFP and
93 * is provided for formatting error messages only.
96 DEFUN (hist_read_rec
, (ifp
, filename
), FILE * ifp AND
const char *filename
)
98 struct gmon_hist_hdr hdr
;
99 bfd_vma n_lowpc
, n_highpc
;
100 int i
, ncnt
, profrate
;
103 if (fread (&hdr
, sizeof (hdr
), 1, ifp
) != 1)
105 fprintf (stderr
, _("%s: %s: unexpected end of file\n"),
110 n_lowpc
= (bfd_vma
) get_vma (core_bfd
, (bfd_byte
*) hdr
.low_pc
);
111 n_highpc
= (bfd_vma
) get_vma (core_bfd
, (bfd_byte
*) hdr
.high_pc
);
112 ncnt
= bfd_get_32 (core_bfd
, (bfd_byte
*) hdr
.hist_size
);
113 profrate
= bfd_get_32 (core_bfd
, (bfd_byte
*) hdr
.prof_rate
);
114 strncpy (hist_dimension
, hdr
.dimen
, sizeof (hdr
.dimen
));
115 hist_dimension
[sizeof (hdr
.dimen
)] = '\0';
116 hist_dimension_abbrev
= hdr
.dimen_abbrev
;
121 /* this is the first histogram record: */
125 lowpc
= (bfd_vma
) n_lowpc
/ sizeof (UNIT
);
126 highpc
= (bfd_vma
) n_highpc
/ sizeof (UNIT
);
127 hist_num_bins
= ncnt
;
132 printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n",
133 (unsigned long) n_lowpc
, (unsigned long) n_highpc
, ncnt
);
134 printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n",
135 (unsigned long) s_lowpc
, (unsigned long) s_highpc
,
137 printf ("[hist_read_rec] lowpc 0x%lx highpc 0x%lx\n",
138 (unsigned long) lowpc
, (unsigned long) highpc
));
140 if (n_lowpc
!= s_lowpc
|| n_highpc
!= s_highpc
141 || ncnt
!= hist_num_bins
|| hz
!= profrate
)
143 fprintf (stderr
, _("%s: `%s' is incompatible with first gmon file\n"),
150 hist_sample
= (int *) xmalloc (hist_num_bins
* sizeof (hist_sample
[0]));
151 memset (hist_sample
, 0, hist_num_bins
* sizeof (hist_sample
[0]));
154 for (i
= 0; i
< hist_num_bins
; ++i
)
156 if (fread (&count
[0], sizeof (count
), 1, ifp
) != 1)
159 _("%s: %s: unexpected EOF after reading %d of %d samples\n"),
160 whoami
, filename
, i
, hist_num_bins
);
163 hist_sample
[i
] += bfd_get_16 (core_bfd
, (bfd_byte
*) & count
[0]);
169 * Write execution histogram to file OFP. FILENAME is the name
170 * of OFP and is provided for formatting error-messages only.
173 DEFUN (hist_write_hist
, (ofp
, filename
), FILE * ofp AND
const char *filename
)
175 struct gmon_hist_hdr hdr
;
182 tag
= GMON_TAG_TIME_HIST
;
183 put_vma (core_bfd
, s_lowpc
, (bfd_byte
*) hdr
.low_pc
);
184 put_vma (core_bfd
, s_highpc
, (bfd_byte
*) hdr
.high_pc
);
185 bfd_put_32 (core_bfd
, hist_num_bins
, (bfd_byte
*) hdr
.hist_size
);
186 bfd_put_32 (core_bfd
, hz
, (bfd_byte
*) hdr
.prof_rate
);
187 strncpy (hdr
.dimen
, hist_dimension
, sizeof (hdr
.dimen
));
188 hdr
.dimen_abbrev
= hist_dimension_abbrev
;
190 if (fwrite (&tag
, sizeof (tag
), 1, ofp
) != 1
191 || fwrite (&hdr
, sizeof (hdr
), 1, ofp
) != 1)
197 for (i
= 0; i
< hist_num_bins
; ++i
)
199 bfd_put_16 (core_bfd
, hist_sample
[i
], (bfd_byte
*) & count
[0]);
200 if (fwrite (&count
[0], sizeof (count
), 1, ofp
) != 1)
210 * Calculate scaled entry point addresses (to save time in
211 * hist_assign_samples), and, on architectures that have procedure
212 * entry masks at the start of a function, possibly push the scaled
213 * entry points over the procedure entry mask, if it turns out that
214 * the entry point is in one bin and the code for a routine is in the
218 scale_and_align_entries ()
221 bfd_vma bin_of_entry
;
224 for (sym
= symtab
.base
; sym
< symtab
.limit
; sym
++)
226 sym
->hist
.scaled_addr
= sym
->addr
/ sizeof (UNIT
);
227 bin_of_entry
= (sym
->hist
.scaled_addr
- lowpc
) / hist_scale
;
228 bin_of_code
= (sym
->hist
.scaled_addr
+ UNITS_TO_CODE
- lowpc
) / hist_scale
;
229 if (bin_of_entry
< bin_of_code
)
232 printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n",
233 (unsigned long) sym
->hist
.scaled_addr
,
234 (unsigned long) (sym
->hist
.scaled_addr
236 sym
->hist
.scaled_addr
+= UNITS_TO_CODE
;
243 * Assign samples to the symbol to which they belong.
245 * Histogram bin I covers some address range [BIN_LOWPC,BIN_HIGH_PC)
246 * which may overlap one more symbol address ranges. If a symbol
247 * overlaps with the bin's address range by O percent, then O percent
248 * of the bin's count is credited to that symbol.
250 * There are three cases as to where BIN_LOW_PC and BIN_HIGH_PC can be
251 * with respect to the symbol's address range [SYM_LOW_PC,
252 * SYM_HIGH_PC) as shown in the following diagram. OVERLAP computes
253 * the distance (in UNITs) between the arrows, the fraction of the
254 * sample that is to be credited to the symbol which starts at
257 * sym_low_pc sym_high_pc
261 * +-----------------------------------------------+
263 * | ->| |<- ->| |<- ->| |<- |
265 * +---------+ +---------+ +---------+
269 * bin_low_pc bin_high_pc bin_low_pc bin_high_pc bin_low_pc bin_high_pc
271 * For the VAX we assert that samples will never fall in the first two
272 * bytes of any routine, since that is the entry mask, thus we call
273 * scale_and_align_entries() to adjust the entry points if the entry
274 * mask falls in one bin but the code for the routine doesn't start
275 * until the next bin. In conjunction with the alignment of routine
276 * addresses, this should allow us to have only one sample for every
277 * four bytes of text space and never have any overlap (the two end
281 DEFUN_VOID (hist_assign_samples
)
283 bfd_vma bin_low_pc
, bin_high_pc
;
284 bfd_vma sym_low_pc
, sym_high_pc
;
285 bfd_vma overlap
, addr
;
290 /* read samples and assign to symbols: */
291 hist_scale
= highpc
- lowpc
;
292 hist_scale
/= hist_num_bins
;
293 scale_and_align_entries ();
295 /* iterate over all sample bins: */
297 for (i
= 0, j
= 1; i
< hist_num_bins
; ++i
)
299 bin_count
= hist_sample
[i
];
304 bin_low_pc
= lowpc
+ (bfd_vma
) (hist_scale
* i
);
305 bin_high_pc
= lowpc
+ (bfd_vma
) (hist_scale
* (i
+ 1));
309 "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
310 (unsigned long) (sizeof (UNIT
) * bin_low_pc
),
311 (unsigned long) (sizeof (UNIT
) * bin_high_pc
),
315 /* credit all symbols that are covered by bin I: */
317 for (j
= j
- 1; j
< symtab
.len
; ++j
)
319 sym_low_pc
= symtab
.base
[j
].hist
.scaled_addr
;
320 sym_high_pc
= symtab
.base
[j
+ 1].hist
.scaled_addr
;
322 * If high end of bin is below entry address, go for next
325 if (bin_high_pc
< sym_low_pc
)
330 * If low end of bin is above high end of symbol, go for
333 if (bin_low_pc
>= sym_high_pc
)
338 MIN (bin_high_pc
, sym_high_pc
) - MAX (bin_low_pc
, sym_low_pc
);
343 "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
344 (unsigned long) symtab
.base
[j
].addr
,
345 (unsigned long) (sizeof (UNIT
) * sym_high_pc
),
346 symtab
.base
[j
].name
, overlap
* time
/ hist_scale
,
348 addr
= symtab
.base
[j
].addr
;
349 credit
= overlap
* time
/ hist_scale
;
351 * Credit symbol if it appears in INCL_FLAT or that
352 * table is empty and it does not appear it in
355 if (sym_lookup (&syms
[INCL_FLAT
], addr
)
356 || (syms
[INCL_FLAT
].len
== 0
357 && !sym_lookup (&syms
[EXCL_FLAT
], addr
)))
359 symtab
.base
[j
].hist
.time
+= credit
;
363 total_time
-= credit
;
368 DBG (SAMPLEDEBUG
, printf ("[assign_samples] total_time %f\n",
374 * Print header for flag histogram profile:
377 DEFUN (print_header
, (prefix
), const char prefix
)
381 sprintf (unit
, _("%c%c/call"), prefix
, hist_dimension_abbrev
);
383 if (bsd_style_output
)
385 printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
386 (long) hist_scale
* sizeof (UNIT
));
387 if (total_time
> 0.0)
389 printf (_(" for %.2f%% of %.2f %s\n\n"),
390 100.0 / total_time
, total_time
/ hz
, hist_dimension
);
395 printf (_("\nEach sample counts as %g %s.\n"), 1.0 / hz
, hist_dimension
);
398 if (total_time
<= 0.0)
400 printf (_(" no time accumulated\n\n"));
401 /* this doesn't hurt since all the numerators will be zero: */
405 printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
406 "% ", _("cumulative"), _("self "), "", _("self "), _("total "), "");
407 printf ("%5.5s %9.9s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
408 _("time"), hist_dimension
, hist_dimension
, _("calls"), unit
, unit
,
414 DEFUN (print_line
, (sym
, scale
), Sym
* sym AND
double scale
)
416 if (ignore_zeros
&& sym
->ncalls
== 0 && sym
->hist
.time
== 0)
421 accum_time
+= sym
->hist
.time
;
422 if (bsd_style_output
)
424 printf ("%5.1f %10.2f %8.2f",
425 total_time
> 0.0 ? 100 * sym
->hist
.time
/ total_time
: 0.0,
426 accum_time
/ hz
, sym
->hist
.time
/ hz
);
430 printf ("%6.2f %9.2f %8.2f",
431 total_time
> 0.0 ? 100 * sym
->hist
.time
/ total_time
: 0.0,
432 accum_time
/ hz
, sym
->hist
.time
/ hz
);
434 if (sym
->ncalls
!= 0)
436 printf (" %8lu %8.2f %8.2f ",
437 sym
->ncalls
, scale
* sym
->hist
.time
/ hz
/ sym
->ncalls
,
438 scale
* (sym
->hist
.time
+ sym
->cg
.child_time
) / hz
/ sym
->ncalls
);
442 printf (" %8.8s %8.8s %8.8s ", "", "", "");
444 if (bsd_style_output
)
450 print_name_only (sym
);
457 * Compare LP and RP. The primary comparison key is execution time,
458 * the secondary is number of invocation, and the tertiary is the
459 * lexicographic order of the function names.
462 DEFUN (cmp_time
, (lp
, rp
), const PTR lp AND
const PTR rp
)
464 const Sym
*left
= *(const Sym
**) lp
;
465 const Sym
*right
= *(const Sym
**) rp
;
468 time_diff
= right
->hist
.time
- left
->hist
.time
;
478 if (right
->ncalls
> left
->ncalls
)
482 if (right
->ncalls
< left
->ncalls
)
487 return strcmp (left
->name
, right
->name
);
492 * Print the flat histogram profile.
495 DEFUN_VOID (hist_print
)
497 Sym
**time_sorted_syms
, *top_dog
, *sym
;
500 double top_time
, time
;
505 first_output
= FALSE
;
513 if (bsd_style_output
)
515 if (print_descriptions
)
517 printf (_("\n\n\nflat profile:\n"));
523 printf (_("Flat profile:\n"));
526 * Sort the symbol table by time (call-count and name as secondary
527 * and tertiary keys):
529 time_sorted_syms
= (Sym
**) xmalloc (symtab
.len
* sizeof (Sym
*));
530 for (index
= 0; index
< symtab
.len
; ++index
)
532 time_sorted_syms
[index
] = &symtab
.base
[index
];
534 qsort (time_sorted_syms
, symtab
.len
, sizeof (Sym
*), cmp_time
);
536 if (bsd_style_output
)
538 log_scale
= 5; /* milli-seconds is BSD-default */
543 * Search for symbol with highest per-call execution time and
549 for (index
= 0; index
< symtab
.len
; ++index
)
551 sym
= time_sorted_syms
[index
];
552 if (sym
->ncalls
!= 0)
554 time
= (sym
->hist
.time
+ sym
->cg
.child_time
) / sym
->ncalls
;
562 if (top_dog
&& top_dog
->ncalls
!= 0 && top_time
> 0.0)
565 while (SItab
[log_scale
].scale
* top_time
< 1000.0
566 && ((size_t) log_scale
567 < sizeof (SItab
) / sizeof (SItab
[0]) - 1))
575 * For now, the dimension is always seconds. In the future, we
576 * may also want to support other (pseudo-)dimensions (such as
577 * I-cache misses etc.).
579 print_header (SItab
[log_scale
].prefix
);
580 for (index
= 0; index
< symtab
.len
; ++index
)
582 addr
= time_sorted_syms
[index
]->addr
;
584 * Print symbol if its in INCL_FLAT table or that table
585 * is empty and the symbol is not in EXCL_FLAT.
587 if (sym_lookup (&syms
[INCL_FLAT
], addr
)
588 || (syms
[INCL_FLAT
].len
== 0
589 && !sym_lookup (&syms
[EXCL_FLAT
], addr
)))
591 print_line (time_sorted_syms
[index
], SItab
[log_scale
].scale
);
594 free (time_sorted_syms
);
596 if (print_descriptions
&& !bsd_style_output
)
This page took 0.041921 seconds and 4 git commands to generate.