2 * Copyright (c) 1983 Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that: (1) source distributions retain this entire copyright
7 * notice and comment, and (2) distributions including binaries display
8 * the following acknowledgement: ``This product includes software
9 * developed by the University of California, Berkeley and its contributors''
10 * in the documentation or other materials provided with the distribution
11 * and in all advertising materials mentioning features or use of this
12 * software. Neither the name of the University nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 static char sccsid
[] = "@(#)printgprof.c 5.7 (Berkeley) 6/1/90";
34 if ( bsd_style_output
) {
37 printf( "\n\n\nflat profile:\n" );
42 printf ("Flat profile:\n");
45 * Sort the symbol table in by time
47 sortednlp
= (nltype
**) calloc( nname
, sizeof(nltype
*) );
48 if ( sortednlp
== (nltype
**) 0 ) {
49 fprintf( stderr
, "[printprof] ran out of memory for time sorting\n" );
51 for ( index
= 0 ; index
< nname
; index
+= 1 ) {
52 sortednlp
[ index
] = &nl
[ index
];
54 qsort( sortednlp
, nname
, sizeof(nltype
*) , timecmp
);
55 for ( index
= 0 ; index
< nname
; index
+= 1 ) {
56 np
= sortednlp
[ index
];
61 if ( bflag
&& !bsd_style_output
) {
66 timecmp( npp1
, npp2
)
67 nltype
**npp1
, **npp2
;
72 timediff
= (*npp2
) -> time
- (*npp1
) -> time
;
77 calldiff
= (*npp2
) -> ncall
- (*npp1
) -> ncall
;
82 return( strcmp( (*npp1
) -> name
, (*npp2
) -> name
) );
86 * header for flatprofline
91 if (bsd_style_output
) {
92 printf( "\ngranularity: each sample hit covers %d byte(s)" ,
93 (long) scale
* sizeof(UNIT
) );
95 printf(" for %.2f%% of %.2f seconds\n\n", 100.0/totime
, totime
/ hz
);
98 printf( "\nEach sample counts as %g seconds.\n",
103 printf(" no time accumulated\n\n");
104 /* This doesn't hurt since all the numerators will be zero. */
107 printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" ,
108 "% " , "cumulative" , "self " , "" , "self " , "total " , "" );
109 printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" ,
110 "time" , "seconds " , "seconds" , "calls" ,
111 "ms/call" , "ms/call" , "name" );
118 if ( zflag
== 0 && np
-> ncall
== 0 && np
-> time
== 0 ) {
121 actime
+= np
-> time
;
122 if (bsd_style_output
)
123 printf( "%5.1f %10.2f %8.2f" ,
124 100 * np
-> time
/ totime
, actime
/ hz
, np
-> time
/ hz
);
126 printf( "%6.2f %9.2f %8.2f" ,
127 100 * np
-> time
/ totime
, actime
/ hz
, np
-> time
/ hz
);
128 if ( np
-> ncall
!= 0 ) {
129 printf( " %8d %8.2f %8.2f " , np
-> ncall
,
130 1000 * np
-> time
/ hz
/ np
-> ncall
,
131 1000 * ( np
-> time
+ np
-> childtime
) / hz
/ np
-> ncall
);
133 printf( " %8.8s %8.8s %8.8s " , "" , "" , "" );
135 if (bsd_style_output
)
145 if (!bsd_style_output
)
147 printf ("\t\t Call graph (explanation follows)\n\n");
149 printf ("\t\t\tCall graph\n\n");
150 printf( "\ngranularity: each sample hit covers %d byte(s)" ,
151 (long) scale
* sizeof(UNIT
) );
152 if ( printtime
> 0.0 ) {
153 printf( " for %.2f%% of %.2f seconds\n\n" ,
154 100.0/printtime
, printtime
/ hz
);
156 printf( " no time propagated\n\n" );
158 * this doesn't hurt, since all the numerators will be 0.0
162 if (bsd_style_output
) {
163 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" ,
164 "" , "" , "" , "" , "called" , "total" , "parents");
165 printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
166 "index" , "%time" , "self" , "descendents" ,
167 "called" , "self" , "name" , "index" );
168 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" ,
169 "" , "" , "" , "" , "called" , "total" , "children");
172 printf( "index %% time self children called name\n" );
179 char kirkbuffer
[ BUFSIZ
];
181 sprintf( kirkbuffer
, "[%d]" , np
-> index
);
182 printf(bsd_style_output
183 ? "%-6.6s %5.1f %7.2f %11.2f"
184 : "%-6.6s %5.1f %7.2f %7.2f" ,
186 100 * ( np
-> propself
+ np
-> propchild
) / printtime
,
187 np
-> propself
/ hz
,
188 np
-> propchild
/ hz
);
189 if ( ( np
-> ncall
+ np
-> selfcalls
) != 0 ) {
190 printf( " %7d" , np
-> ncall
);
191 if ( np
-> selfcalls
!= 0 ) {
192 printf( "+%-7d " , np
-> selfcalls
);
194 printf( " %7.7s " , "" );
197 printf( " %7.7s %7.7s " , "" , "" );
203 printgprof(timesortnlp
)
204 nltype
**timesortnlp
;
210 * Print out the structured profiling list
212 if ( bflag
&& bsd_style_output
) {
213 bsd_callg_blurb(stdout
);
216 for ( index
= 0 ; index
< nname
+ ncycle
; index
++ ) {
217 parentp
= timesortnlp
[ index
];
219 parentp
-> ncall
== 0 &&
220 parentp
-> selfcalls
== 0 &&
221 parentp
-> propself
== 0 &&
222 parentp
-> propchild
== 0 ) {
225 if ( ! parentp
-> printflag
) {
228 if ( parentp
-> name
== 0 && parentp
-> cycleno
!= 0 ) {
232 printcycle( parentp
);
233 printmembers( parentp
);
235 printparents( parentp
);
236 gprofline( parentp
);
237 printchildren( parentp
);
239 if (bsd_style_output
)
241 printf( "-----------------------------------------------\n" );
242 if (bsd_style_output
)
246 if ( bflag
&& !bsd_style_output
) {
247 fsf_callg_blurb(stdout
);
252 * sort by decreasing propagated time
253 * if times are equal, but one is a cycle header,
254 * say that's first (e.g. less, i.e. -1).
255 * if one's name doesn't have an underscore and the other does,
256 * say the one is first.
257 * all else being equal, sort by names.
260 totalcmp( npp1
, npp2
)
264 register nltype
*np1
= *npp1
;
265 register nltype
*np2
= *npp2
;
268 diff
= ( np1
-> propself
+ np1
-> propchild
)
269 - ( np2
-> propself
+ np2
-> propchild
);
274 if ( np1
-> name
== 0 && np1
-> cycleno
!= 0 )
276 if ( np2
-> name
== 0 && np2
-> cycleno
!= 0 )
278 if ( np1
-> name
== 0 )
280 if ( np2
-> name
== 0 )
282 if ( *(np1
-> name
) != '_' && *(np2
-> name
) == '_' )
284 if ( *(np1
-> name
) == '_' && *(np2
-> name
) != '_' )
286 if ( np1
-> ncall
> np2
-> ncall
)
288 if ( np1
-> ncall
< np2
-> ncall
)
290 return strcmp( np1
-> name
, np2
-> name
);
293 printparents( childp
)
300 if ( childp
-> cyclehead
!= 0 ) {
301 cycleheadp
= childp
-> cyclehead
;
305 if ( childp
-> parents
== 0 ) {
306 printf(bsd_style_output
307 ? "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n"
308 : "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s <spontaneous>\n" ,
309 "" , "" , "" , "" , "" , "" );
312 sortparents( childp
);
313 for ( arcp
= childp
-> parents
; arcp
; arcp
= arcp
-> arc_parentlist
) {
314 parentp
= arcp
-> arc_parentp
;
315 if ( childp
== parentp
||
316 ( childp
->cycleno
!= 0 && parentp
->cycleno
== childp
->cycleno
) ) {
318 * selfcall or call among siblings
320 printf(bsd_style_output
321 ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s "
322 : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s " ,
324 arcp
-> arc_count
, "" );
325 printname( parentp
);
329 * regular parent of child
331 printf(bsd_style_output
332 ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d "
333 : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ",
335 arcp
-> arc_time
/ hz
, arcp
-> arc_childtime
/ hz
,
336 arcp
-> arc_count
, cycleheadp
-> ncall
);
337 printname( parentp
);
343 printchildren( parentp
)
349 sortchildren( parentp
);
350 arcp
= parentp
-> children
;
351 for ( arcp
= parentp
-> children
; arcp
; arcp
= arcp
-> arc_childlist
) {
352 childp
= arcp
-> arc_childp
;
353 if ( childp
== parentp
||
354 ( childp
->cycleno
!= 0 && childp
->cycleno
== parentp
->cycleno
) ) {
356 * self call or call to sibling
358 printf(bsd_style_output
359 ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s "
360 : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s " ,
361 "" , "" , "" , "" , arcp
-> arc_count
, "" );
366 * regular child of parent
368 printf(bsd_style_output
369 ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d "
370 : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d " ,
372 arcp
-> arc_time
/ hz
, arcp
-> arc_childtime
/ hz
,
373 arcp
-> arc_count
, childp
-> cyclehead
-> ncall
);
380 /* Print name of symbol. Return number of characters printed. */
383 printnameonly ( selfp
)
387 CONST
char *name
= selfp
->name
;
389 char *demangled
= NULL
;
390 if (!bsd_style_output
) {
391 if (name
[0] == '_' && name
[1] && discard_underscores
)
393 demangled
= cplus_demangle (name
, DMGL_ANSI
|DMGL_PARAMS
);
397 printf( "%s" , name
);
398 size
= strlen (name
);
402 if ( debug
& DFNDEBUG
) {
403 printf( "{%d} " , selfp
-> toporder
);
405 if ( debug
& PROPDEBUG
) {
406 printf( "%5.2f%% " , selfp
-> propfraction
);
416 printnameonly (selfp
);
418 if ( selfp
-> cycleno
!= 0 ) {
419 printf( " <cycle %d>" , selfp
-> cycleno
);
421 if ( selfp
-> index
!= 0 ) {
422 if ( selfp
-> printflag
) {
423 printf( " [%d]" , selfp
-> index
);
425 printf( " (%d)" , selfp
-> index
);
430 sortchildren( parentp
)
439 * unlink children from parent,
440 * then insertion sort back on to sorted's children.
441 * *arcp the arc you have detached and are inserting.
442 * *detachedp the rest of the arcs to be sorted.
443 * sorted arc list onto which you insertion sort.
444 * *prevp arc before the arc you are comparing.
446 sorted
.arc_childlist
= 0;
447 for ( (arcp
= parentp
-> children
)&&(detachedp
= arcp
-> arc_childlist
);
449 (arcp
= detachedp
)&&(detachedp
= detachedp
-> arc_childlist
)) {
451 * consider *arcp as disconnected
452 * insert it into sorted
454 for ( prevp
= &sorted
;
455 prevp
-> arc_childlist
;
456 prevp
= prevp
-> arc_childlist
) {
457 if ( arccmp( arcp
, prevp
-> arc_childlist
) != LESSTHAN
) {
461 arcp
-> arc_childlist
= prevp
-> arc_childlist
;
462 prevp
-> arc_childlist
= arcp
;
465 * reattach sorted children to parent
467 parentp
-> children
= sorted
.arc_childlist
;
470 sortparents( childp
)
479 * unlink parents from child,
480 * then insertion sort back on to sorted's parents.
481 * *arcp the arc you have detached and are inserting.
482 * *detachedp the rest of the arcs to be sorted.
483 * sorted arc list onto which you insertion sort.
484 * *prevp arc before the arc you are comparing.
486 sorted
.arc_parentlist
= 0;
487 for ( (arcp
= childp
-> parents
)&&(detachedp
= arcp
-> arc_parentlist
);
489 (arcp
= detachedp
)&&(detachedp
= detachedp
-> arc_parentlist
)) {
491 * consider *arcp as disconnected
492 * insert it into sorted
494 for ( prevp
= &sorted
;
495 prevp
-> arc_parentlist
;
496 prevp
= prevp
-> arc_parentlist
) {
497 if ( arccmp( arcp
, prevp
-> arc_parentlist
) != GREATERTHAN
) {
501 arcp
-> arc_parentlist
= prevp
-> arc_parentlist
;
502 prevp
-> arc_parentlist
= arcp
;
505 * reattach sorted arcs to child
507 childp
-> parents
= sorted
.arc_parentlist
;
511 * print a cycle header
516 char kirkbuffer
[ BUFSIZ
];
518 sprintf( kirkbuffer
, "[%d]" , cyclep
-> index
);
519 printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
521 100 * ( cyclep
-> propself
+ cyclep
-> propchild
) / printtime
,
522 cyclep
-> propself
/ hz
,
523 cyclep
-> propchild
/ hz
,
525 if ( cyclep
-> selfcalls
!= 0 ) {
526 printf( "+%-7d" , cyclep
-> selfcalls
);
528 printf( " %7.7s" , "" );
530 printf( " <cycle %d as a whole>\t[%d]\n" ,
531 cyclep
-> cycleno
, cyclep
-> index
);
535 * print the members of a cycle
537 printmembers( cyclep
)
542 sortmembers( cyclep
);
543 for ( memberp
= cyclep
-> cnext
; memberp
; memberp
= memberp
-> cnext
) {
544 printf( "%6.6s %5.5s %7.2f %11.2f %7d" ,
545 "" , "" , memberp
-> propself
/ hz
, memberp
-> propchild
/ hz
,
547 if ( memberp
-> selfcalls
!= 0 ) {
548 printf( "+%-7d" , memberp
-> selfcalls
);
550 printf( " %7.7s" , "" );
553 printname( memberp
);
559 * sort members of a cycle
561 sortmembers( cyclep
)
569 * detach cycle members from cyclehead,
570 * and insertion sort them back on.
572 todo
= cyclep
-> cnext
;
574 for ( (doing
= todo
)&&(todo
= doing
-> cnext
);
576 (doing
= todo
)&&(todo
= doing
-> cnext
)){
577 for ( prev
= cyclep
; prev
-> cnext
; prev
= prev
-> cnext
) {
578 if ( membercmp( doing
, prev
-> cnext
) == GREATERTHAN
) {
582 doing
-> cnext
= prev
-> cnext
;
583 prev
-> cnext
= doing
;
588 * major sort is on propself + propchild,
589 * next is sort on ncalls + selfcalls.
592 membercmp( this , that
)
596 double thistime
= this -> propself
+ this -> propchild
;
597 double thattime
= that
-> propself
+ that
-> propchild
;
598 long thiscalls
= this -> ncall
+ this -> selfcalls
;
599 long thatcalls
= that
-> ncall
+ that
-> selfcalls
;
601 if ( thistime
> thattime
) {
604 if ( thistime
< thattime
) {
607 if ( thiscalls
> thatcalls
) {
610 if ( thiscalls
< thatcalls
) {
616 * compare two arcs to/from the same child/parent.
617 * - if one arc is a self arc, it's least.
618 * - if one arc is within a cycle, it's less than.
619 * - if both arcs are within a cycle, compare arc counts.
620 * - if neither arc is within a cycle, compare with
621 * arc_time + arc_childtime as major key
622 * arc count as minor key
625 arccmp( thisp
, thatp
)
629 nltype
*thisparentp
= thisp
-> arc_parentp
;
630 nltype
*thischildp
= thisp
-> arc_childp
;
631 nltype
*thatparentp
= thatp
-> arc_parentp
;
632 nltype
*thatchildp
= thatp
-> arc_childp
;
637 if ( debug
& TIMEDEBUG
) {
638 printf( "[arccmp] " );
639 printname( thisparentp
);
641 printname ( thischildp
);
642 printf( " %f + %f %d/%d\n" ,
643 thisp
-> arc_time
, thisp
-> arc_childtime
,
644 thisp
-> arc_count
, thischildp
-> ncall
);
645 printf( "[arccmp] " );
646 printname( thatparentp
);
648 printname( thatchildp
);
649 printf( " %f + %f %d/%d\n" ,
650 thatp
-> arc_time
, thatp
-> arc_childtime
,
651 thatp
-> arc_count
, thatchildp
-> ncall
);
655 if ( thisparentp
== thischildp
) {
656 /* this is a self call */
659 if ( thatparentp
== thatchildp
) {
660 /* that is a self call */
663 if ( thisparentp
-> cycleno
!= 0 && thischildp
-> cycleno
!= 0 &&
664 thisparentp
-> cycleno
== thischildp
-> cycleno
) {
665 /* this is a call within a cycle */
666 if ( thatparentp
-> cycleno
!= 0 && thatchildp
-> cycleno
!= 0 &&
667 thatparentp
-> cycleno
== thatchildp
-> cycleno
) {
668 /* that is a call within the cycle, too */
669 if ( thisp
-> arc_count
< thatp
-> arc_count
) {
672 if ( thisp
-> arc_count
> thatp
-> arc_count
) {
677 /* that isn't a call within the cycle */
681 /* this isn't a call within a cycle */
682 if ( thatparentp
-> cycleno
!= 0 && thatchildp
-> cycleno
!= 0 &&
683 thatparentp
-> cycleno
== thatchildp
-> cycleno
) {
684 /* that is a call within a cycle */
687 /* neither is a call within a cycle */
688 thistime
= thisp
-> arc_time
+ thisp
-> arc_childtime
;
689 thattime
= thatp
-> arc_time
+ thatp
-> arc_childtime
;
690 if ( thistime
< thattime
)
692 if ( thistime
> thattime
)
694 if ( thisp
-> arc_count
< thatp
-> arc_count
)
696 if ( thisp
-> arc_count
> thatp
-> arc_count
)
704 namecmp( npp1
, npp2
)
705 nltype
**npp1
, **npp2
;
707 return( strcmp( (*npp1
) -> name
, (*npp2
) -> name
) );
712 nltype
**namesortnlp
;
713 register nltype
*nlp
;
714 int index
, nnames
, todo
, i
, j
;
715 char peterbuffer
[20];
718 * Now, sort regular function name alphbetically
719 * to create an index.
721 namesortnlp
= (nltype
**) calloc( nname
+ ncycle
, sizeof(nltype
*) );
722 if ( namesortnlp
== (nltype
**) 0 ) {
723 fprintf( stderr
, "%s: ran out of memory for sorting\n" , whoami
);
725 for ( index
= 0 , nnames
= 0 ; index
< nname
; index
++ ) {
726 if ( zflag
== 0 && nl
[index
].ncall
== 0 && nl
[index
].time
== 0 )
728 namesortnlp
[nnames
++] = &nl
[index
];
730 qsort( namesortnlp
, nnames
, sizeof(nltype
*) , namecmp
);
731 for ( index
= 1 , todo
= nnames
; index
<= ncycle
; index
++ ) {
732 namesortnlp
[todo
++] = &cyclenl
[index
];
734 printf( "\f\nIndex by function name\n\n" );
735 index
= ( todo
+ 2 ) / 3;
736 for ( i
= 0; i
< index
; i
++ ) {
737 for ( j
= i
; j
< todo
; j
+= index
) {
738 nlp
= namesortnlp
[ j
];
739 if ( nlp
-> printflag
) {
740 sprintf( peterbuffer
, "[%d]" , nlp
-> index
);
742 sprintf( peterbuffer
, "(%d)" , nlp
-> index
);
745 printf( "%6.6s " , peterbuffer
);
746 if (bsd_style_output
)
747 printf ("%-19.19s" , nlp
->name
);
749 int size
= printnameonly(nlp
);
750 for ( ; size
< 19; size
++) putchar(' ');
753 printf( "%6.6s " , peterbuffer
);
754 sprintf( peterbuffer
, "<cycle %d>" , nlp
-> cycleno
);
755 printf( "%-19.19s" , peterbuffer
);
767 PTR val
= (PTR
) malloc (size
);
769 fprintf (stderr
, "virtual memory exhaused\n");
776 xrealloc (oldval
, size
)
780 PTR val
= (PTR
) realloc (oldval
, size
);
782 fprintf (stderr
, "virtual memory exhaused\n");
This page took 0.04659 seconds and 4 git commands to generate.