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" ,
96 100.0/totime
, totime
/ hz
);
98 printf( " no time accumulated\n\n" );
100 * this doesn't hurt since all the numerators will be zero.
106 printf( "\nEach sample counts as %g seconds.\n",
109 printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" ,
110 "% " , "cumulative" , "self " , "" , "self " , "total " , "" );
111 printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" ,
112 "time" , "seconds " , "seconds" , "calls" ,
113 "ms/call" , "ms/call" , "name" );
120 if ( zflag
== 0 && np
-> ncall
== 0 && np
-> time
== 0 ) {
123 actime
+= np
-> time
;
124 if (bsd_style_output
)
125 printf( "%5.1f %10.2f %8.2f" ,
126 100 * np
-> time
/ totime
, actime
/ hz
, np
-> time
/ hz
);
128 printf( "%6.2f %9.2f %8.2f" ,
129 100 * np
-> time
/ totime
, actime
/ hz
, np
-> time
/ hz
);
130 if ( np
-> ncall
!= 0 ) {
131 printf( " %8d %8.2f %8.2f " , np
-> ncall
,
132 1000 * np
-> time
/ hz
/ np
-> ncall
,
133 1000 * ( np
-> time
+ np
-> childtime
) / hz
/ np
-> ncall
);
135 printf( " %8.8s %8.8s %8.8s " , "" , "" , "" );
137 if (bsd_style_output
)
147 if (!bsd_style_output
)
149 printf ("\t\t Call graph (explanation follows)\n\n");
151 printf ("\t\t\tCall graph\n\n");
152 printf( "\ngranularity: each sample hit covers %d byte(s)" ,
153 (long) scale
* sizeof(UNIT
) );
154 if ( printtime
> 0.0 ) {
155 printf( " for %.2f%% of %.2f seconds\n\n" ,
156 100.0/printtime
, printtime
/ hz
);
158 printf( " no time propagated\n\n" );
160 * this doesn't hurt, since all the numerators will be 0.0
164 if (bsd_style_output
) {
165 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" ,
166 "" , "" , "" , "" , "called" , "total" , "parents");
167 printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
168 "index" , "%time" , "self" , "descendents" ,
169 "called" , "self" , "name" , "index" );
170 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" ,
171 "" , "" , "" , "" , "called" , "total" , "children");
174 printf( "index %% time self children called name\n" );
181 char kirkbuffer
[ BUFSIZ
];
183 sprintf( kirkbuffer
, "[%d]" , np
-> index
);
184 printf(bsd_style_output
185 ? "%-6.6s %5.1f %7.2f %11.2f"
186 : "%-6.6s %5.1f %7.2f %7.2f" ,
188 100 * ( np
-> propself
+ np
-> propchild
) / printtime
,
189 np
-> propself
/ hz
,
190 np
-> propchild
/ hz
);
191 if ( ( np
-> ncall
+ np
-> selfcalls
) != 0 ) {
192 printf( " %7d" , np
-> ncall
);
193 if ( np
-> selfcalls
!= 0 ) {
194 printf( "+%-7d " , np
-> selfcalls
);
196 printf( " %7.7s " , "" );
199 printf( " %7.7s %7.7s " , "" , "" );
205 printgprof(timesortnlp
)
206 nltype
**timesortnlp
;
212 * Print out the structured profiling list
214 if ( bflag
&& bsd_style_output
) {
215 bsd_callg_blurb(stdout
);
218 for ( index
= 0 ; index
< nname
+ ncycle
; index
++ ) {
219 parentp
= timesortnlp
[ index
];
221 parentp
-> ncall
== 0 &&
222 parentp
-> selfcalls
== 0 &&
223 parentp
-> propself
== 0 &&
224 parentp
-> propchild
== 0 ) {
227 if ( ! parentp
-> printflag
) {
230 if ( parentp
-> name
== 0 && parentp
-> cycleno
!= 0 ) {
234 printcycle( parentp
);
235 printmembers( parentp
);
237 printparents( parentp
);
238 gprofline( parentp
);
239 printchildren( parentp
);
241 if (bsd_style_output
)
243 printf( "-----------------------------------------------\n" );
244 if (bsd_style_output
)
247 cfree( timesortnlp
);
248 if ( bflag
&& !bsd_style_output
) {
249 fsf_callg_blurb(stdout
);
254 * sort by decreasing propagated time
255 * if times are equal, but one is a cycle header,
256 * say that's first (e.g. less, i.e. -1).
257 * if one's name doesn't have an underscore and the other does,
258 * say the one is first.
259 * all else being equal, sort by names.
262 totalcmp( npp1
, npp2
)
266 register nltype
*np1
= *npp1
;
267 register nltype
*np2
= *npp2
;
270 diff
= ( np1
-> propself
+ np1
-> propchild
)
271 - ( np2
-> propself
+ np2
-> propchild
);
276 if ( np1
-> name
== 0 && np1
-> cycleno
!= 0 )
278 if ( np2
-> name
== 0 && np2
-> cycleno
!= 0 )
280 if ( np1
-> name
== 0 )
282 if ( np2
-> name
== 0 )
284 if ( *(np1
-> name
) != '_' && *(np2
-> name
) == '_' )
286 if ( *(np1
-> name
) == '_' && *(np2
-> name
) != '_' )
288 if ( np1
-> ncall
> np2
-> ncall
)
290 if ( np1
-> ncall
< np2
-> ncall
)
292 return strcmp( np1
-> name
, np2
-> name
);
295 printparents( childp
)
302 if ( childp
-> cyclehead
!= 0 ) {
303 cycleheadp
= childp
-> cyclehead
;
307 if ( childp
-> parents
== 0 ) {
308 printf(bsd_style_output
309 ? "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n"
310 : "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s <spontaneous>\n" ,
311 "" , "" , "" , "" , "" , "" );
314 sortparents( childp
);
315 for ( arcp
= childp
-> parents
; arcp
; arcp
= arcp
-> arc_parentlist
) {
316 parentp
= arcp
-> arc_parentp
;
317 if ( childp
== parentp
||
318 ( childp
->cycleno
!= 0 && parentp
->cycleno
== childp
->cycleno
) ) {
320 * selfcall or call among siblings
322 printf(bsd_style_output
323 ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s "
324 : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s " ,
326 arcp
-> arc_count
, "" );
327 printname( parentp
);
331 * regular parent of child
333 printf(bsd_style_output
334 ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d "
335 : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ",
337 arcp
-> arc_time
/ hz
, arcp
-> arc_childtime
/ hz
,
338 arcp
-> arc_count
, cycleheadp
-> ncall
);
339 printname( parentp
);
345 printchildren( parentp
)
351 sortchildren( parentp
);
352 arcp
= parentp
-> children
;
353 for ( arcp
= parentp
-> children
; arcp
; arcp
= arcp
-> arc_childlist
) {
354 childp
= arcp
-> arc_childp
;
355 if ( childp
== parentp
||
356 ( childp
->cycleno
!= 0 && childp
->cycleno
== parentp
->cycleno
) ) {
358 * self call or call to sibling
360 printf(bsd_style_output
361 ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s "
362 : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s " ,
363 "" , "" , "" , "" , arcp
-> arc_count
, "" );
368 * regular child of parent
370 printf(bsd_style_output
371 ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d "
372 : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d " ,
374 arcp
-> arc_time
/ hz
, arcp
-> arc_childtime
/ hz
,
375 arcp
-> arc_count
, childp
-> cyclehead
-> ncall
);
382 /* Print name of symbol. Return number of characters printed. */
385 printnameonly ( selfp
)
389 CONST
char *name
= selfp
->name
;
391 char *demangled
= NULL
;
392 if (!bsd_style_output
) {
393 if (name
[0] == '_' && name
[1] && discard_underscores
)
395 demangled
= cplus_demangle (name
, DMGL_ANSI
|DMGL_PARAMS
);
399 printf( "%s" , name
);
400 size
= strlen (name
);
404 if ( debug
& DFNDEBUG
) {
405 printf( "{%d} " , selfp
-> toporder
);
407 if ( debug
& PROPDEBUG
) {
408 printf( "%5.2f%% " , selfp
-> propfraction
);
418 printnameonly (selfp
);
420 if ( selfp
-> cycleno
!= 0 ) {
421 printf( " <cycle %d>" , selfp
-> cycleno
);
423 if ( selfp
-> index
!= 0 ) {
424 if ( selfp
-> printflag
) {
425 printf( " [%d]" , selfp
-> index
);
427 printf( " (%d)" , selfp
-> index
);
432 sortchildren( parentp
)
441 * unlink children from parent,
442 * then insertion sort back on to sorted's children.
443 * *arcp the arc you have detached and are inserting.
444 * *detachedp the rest of the arcs to be sorted.
445 * sorted arc list onto which you insertion sort.
446 * *prevp arc before the arc you are comparing.
448 sorted
.arc_childlist
= 0;
449 for ( (arcp
= parentp
-> children
)&&(detachedp
= arcp
-> arc_childlist
);
451 (arcp
= detachedp
)&&(detachedp
= detachedp
-> arc_childlist
)) {
453 * consider *arcp as disconnected
454 * insert it into sorted
456 for ( prevp
= &sorted
;
457 prevp
-> arc_childlist
;
458 prevp
= prevp
-> arc_childlist
) {
459 if ( arccmp( arcp
, prevp
-> arc_childlist
) != LESSTHAN
) {
463 arcp
-> arc_childlist
= prevp
-> arc_childlist
;
464 prevp
-> arc_childlist
= arcp
;
467 * reattach sorted children to parent
469 parentp
-> children
= sorted
.arc_childlist
;
472 sortparents( childp
)
481 * unlink parents from child,
482 * then insertion sort back on to sorted's parents.
483 * *arcp the arc you have detached and are inserting.
484 * *detachedp the rest of the arcs to be sorted.
485 * sorted arc list onto which you insertion sort.
486 * *prevp arc before the arc you are comparing.
488 sorted
.arc_parentlist
= 0;
489 for ( (arcp
= childp
-> parents
)&&(detachedp
= arcp
-> arc_parentlist
);
491 (arcp
= detachedp
)&&(detachedp
= detachedp
-> arc_parentlist
)) {
493 * consider *arcp as disconnected
494 * insert it into sorted
496 for ( prevp
= &sorted
;
497 prevp
-> arc_parentlist
;
498 prevp
= prevp
-> arc_parentlist
) {
499 if ( arccmp( arcp
, prevp
-> arc_parentlist
) != GREATERTHAN
) {
503 arcp
-> arc_parentlist
= prevp
-> arc_parentlist
;
504 prevp
-> arc_parentlist
= arcp
;
507 * reattach sorted arcs to child
509 childp
-> parents
= sorted
.arc_parentlist
;
513 * print a cycle header
518 char kirkbuffer
[ BUFSIZ
];
520 sprintf( kirkbuffer
, "[%d]" , cyclep
-> index
);
521 printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
523 100 * ( cyclep
-> propself
+ cyclep
-> propchild
) / printtime
,
524 cyclep
-> propself
/ hz
,
525 cyclep
-> propchild
/ hz
,
527 if ( cyclep
-> selfcalls
!= 0 ) {
528 printf( "+%-7d" , cyclep
-> selfcalls
);
530 printf( " %7.7s" , "" );
532 printf( " <cycle %d as a whole>\t[%d]\n" ,
533 cyclep
-> cycleno
, cyclep
-> index
);
537 * print the members of a cycle
539 printmembers( cyclep
)
544 sortmembers( cyclep
);
545 for ( memberp
= cyclep
-> cnext
; memberp
; memberp
= memberp
-> cnext
) {
546 printf( "%6.6s %5.5s %7.2f %11.2f %7d" ,
547 "" , "" , memberp
-> propself
/ hz
, memberp
-> propchild
/ hz
,
549 if ( memberp
-> selfcalls
!= 0 ) {
550 printf( "+%-7d" , memberp
-> selfcalls
);
552 printf( " %7.7s" , "" );
555 printname( memberp
);
561 * sort members of a cycle
563 sortmembers( cyclep
)
571 * detach cycle members from cyclehead,
572 * and insertion sort them back on.
574 todo
= cyclep
-> cnext
;
576 for ( (doing
= todo
)&&(todo
= doing
-> cnext
);
578 (doing
= todo
)&&(todo
= doing
-> cnext
)){
579 for ( prev
= cyclep
; prev
-> cnext
; prev
= prev
-> cnext
) {
580 if ( membercmp( doing
, prev
-> cnext
) == GREATERTHAN
) {
584 doing
-> cnext
= prev
-> cnext
;
585 prev
-> cnext
= doing
;
590 * major sort is on propself + propchild,
591 * next is sort on ncalls + selfcalls.
594 membercmp( this , that
)
598 double thistime
= this -> propself
+ this -> propchild
;
599 double thattime
= that
-> propself
+ that
-> propchild
;
600 long thiscalls
= this -> ncall
+ this -> selfcalls
;
601 long thatcalls
= that
-> ncall
+ that
-> selfcalls
;
603 if ( thistime
> thattime
) {
606 if ( thistime
< thattime
) {
609 if ( thiscalls
> thatcalls
) {
612 if ( thiscalls
< thatcalls
) {
618 * compare two arcs to/from the same child/parent.
619 * - if one arc is a self arc, it's least.
620 * - if one arc is within a cycle, it's less than.
621 * - if both arcs are within a cycle, compare arc counts.
622 * - if neither arc is within a cycle, compare with
623 * arc_time + arc_childtime as major key
624 * arc count as minor key
627 arccmp( thisp
, thatp
)
631 nltype
*thisparentp
= thisp
-> arc_parentp
;
632 nltype
*thischildp
= thisp
-> arc_childp
;
633 nltype
*thatparentp
= thatp
-> arc_parentp
;
634 nltype
*thatchildp
= thatp
-> arc_childp
;
639 if ( debug
& TIMEDEBUG
) {
640 printf( "[arccmp] " );
641 printname( thisparentp
);
643 printname ( thischildp
);
644 printf( " %f + %f %d/%d\n" ,
645 thisp
-> arc_time
, thisp
-> arc_childtime
,
646 thisp
-> arc_count
, thischildp
-> ncall
);
647 printf( "[arccmp] " );
648 printname( thatparentp
);
650 printname( thatchildp
);
651 printf( " %f + %f %d/%d\n" ,
652 thatp
-> arc_time
, thatp
-> arc_childtime
,
653 thatp
-> arc_count
, thatchildp
-> ncall
);
657 if ( thisparentp
== thischildp
) {
658 /* this is a self call */
661 if ( thatparentp
== thatchildp
) {
662 /* that is a self call */
665 if ( thisparentp
-> cycleno
!= 0 && thischildp
-> cycleno
!= 0 &&
666 thisparentp
-> cycleno
== thischildp
-> cycleno
) {
667 /* this is a call within a cycle */
668 if ( thatparentp
-> cycleno
!= 0 && thatchildp
-> cycleno
!= 0 &&
669 thatparentp
-> cycleno
== thatchildp
-> cycleno
) {
670 /* that is a call within the cycle, too */
671 if ( thisp
-> arc_count
< thatp
-> arc_count
) {
674 if ( thisp
-> arc_count
> thatp
-> arc_count
) {
679 /* that isn't a call within the cycle */
683 /* this isn't a call within a cycle */
684 if ( thatparentp
-> cycleno
!= 0 && thatchildp
-> cycleno
!= 0 &&
685 thatparentp
-> cycleno
== thatchildp
-> cycleno
) {
686 /* that is a call within a cycle */
689 /* neither is a call within a cycle */
690 thistime
= thisp
-> arc_time
+ thisp
-> arc_childtime
;
691 thattime
= thatp
-> arc_time
+ thatp
-> arc_childtime
;
692 if ( thistime
< thattime
)
694 if ( thistime
> thattime
)
696 if ( thisp
-> arc_count
< thatp
-> arc_count
)
698 if ( thisp
-> arc_count
> thatp
-> arc_count
)
706 namecmp( npp1
, npp2
)
707 nltype
**npp1
, **npp2
;
709 return( strcmp( (*npp1
) -> name
, (*npp2
) -> name
) );
714 nltype
**namesortnlp
;
715 register nltype
*nlp
;
716 int index
, nnames
, todo
, i
, j
;
717 char peterbuffer
[20];
720 * Now, sort regular function name alphbetically
721 * to create an index.
723 namesortnlp
= (nltype
**) calloc( nname
+ ncycle
, sizeof(nltype
*) );
724 if ( namesortnlp
== (nltype
**) 0 ) {
725 fprintf( stderr
, "%s: ran out of memory for sorting\n" , whoami
);
727 for ( index
= 0 , nnames
= 0 ; index
< nname
; index
++ ) {
728 if ( zflag
== 0 && nl
[index
].ncall
== 0 && nl
[index
].time
== 0 )
730 namesortnlp
[nnames
++] = &nl
[index
];
732 qsort( namesortnlp
, nnames
, sizeof(nltype
*) , namecmp
);
733 for ( index
= 1 , todo
= nnames
; index
<= ncycle
; index
++ ) {
734 namesortnlp
[todo
++] = &cyclenl
[index
];
736 printf( "\f\nIndex by function name\n\n" );
737 index
= ( todo
+ 2 ) / 3;
738 for ( i
= 0; i
< index
; i
++ ) {
739 for ( j
= i
; j
< todo
; j
+= index
) {
740 nlp
= namesortnlp
[ j
];
741 if ( nlp
-> printflag
) {
742 sprintf( peterbuffer
, "[%d]" , nlp
-> index
);
744 sprintf( peterbuffer
, "(%d)" , nlp
-> index
);
747 printf( "%6.6s " , peterbuffer
);
748 if (bsd_style_output
)
749 printf ("%-19.19s" , nlp
->name
);
751 int size
= printnameonly(nlp
);
752 for ( ; size
< 19; size
++) putchar(' ');
755 printf( "%6.6s " , peterbuffer
);
756 sprintf( peterbuffer
, "<cycle %d>" , nlp
-> cycleno
);
757 printf( "%-19.19s" , peterbuffer
);
762 cfree( namesortnlp
);
769 PTR val
= (PTR
) malloc (size
);
771 fprintf (stderr
, "virtual memory exhaused\n");
778 xrealloc (oldval
, size
)
782 PTR val
= (PTR
) realloc (oldval
, size
);
784 fprintf (stderr
, "virtual memory exhaused\n");
This page took 0.044688 seconds and 4 git commands to generate.