date and time created 83/02/11 15:44:35 by rrh
[unix-history] / usr / src / usr.bin / gprof / printgprof.c
CommitLineData
873be5f6 1#ifndef lint
bc19d06b 2 static char *sccsid = "@(#)printgprof.c 1.13 (Berkeley) %G%";
873be5f6
PK
3#endif lint
4
31f0a970 5#include "gprof.h"
873be5f6 6
68fa3db5
PK
7printprof()
8{
9 register nltype *np;
10 nltype **sortednlp;
11 int index;
12
7ec9eedc
PK
13 printf( "\ngranularity: each sample hit covers %d byte(s)" ,
14 (long) scale * sizeof(UNIT) );
54c5b05a
PK
15 if ( totime > 0.0 ) {
16 printf( " for %.2f%% of %.2f seconds\n\n" ,
89bcca98 17 100.0/totime , totime / hz );
54c5b05a
PK
18 } else {
19 printf( " no time accumulated\n\n" );
20 /*
21 * this doesn't hurt sinc eall the numerators will be zero.
22 */
23 totime = 1.0;
24 }
68fa3db5
PK
25 actime = 0.0;
26 flatprofheader();
27 /*
28 * Sort the symbol table in by time
29 */
30 sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
31 if ( sortednlp == (nltype **) 0 ) {
32 fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
33 }
34 for ( index = 0 ; index < nname ; index += 1 ) {
35 sortednlp[ index ] = &nl[ index ];
36 }
37 qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
38 for ( index = 0 ; index < nname ; index += 1 ) {
39 np = sortednlp[ index ];
40 flatprofline( np );
41 }
42 actime = 0.0;
68fa3db5
PK
43}
44
45timecmp( npp1 , npp2 )
46 nltype **npp1, **npp2;
47{
f3d4b802
PK
48 double timediff;
49 long calldiff;
68fa3db5 50
f3d4b802
PK
51 timediff = (*npp2) -> time - (*npp1) -> time;
52 if ( timediff > 0.0 )
68fa3db5 53 return 1 ;
f3d4b802
PK
54 if ( timediff < 0.0 )
55 return -1;
56 calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
57 if ( calldiff > 0 )
58 return 1;
59 if ( calldiff < 0 )
68fa3db5
PK
60 return -1;
61 return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
62}
63
64 /*
65 * header for flatprofline
66 */
67flatprofheader()
68{
69
8b570c5c 70 if ( bflag ) {
bc19d06b 71 printblurb( FLAT_BLURB );
8b570c5c 72 }
68fa3db5
PK
73 printf( "%5.5s %7.7s %7.7s %7.7s %-8.8s\n" ,
74 "%time" , "cumsecs" , "seconds" , "calls" , "name" );
75}
76
77flatprofline( np )
78 register nltype *np;
79{
80
8b570c5c 81 if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
68fa3db5
PK
82 return;
83 }
84 actime += np -> time;
85 printf( "%5.1f %7.2f %7.2f" ,
89bcca98 86 100 * np -> time / totime , actime / hz , np -> time / hz );
68fa3db5
PK
87 if ( np -> ncall != 0 ) {
88 printf( " %7d" , np -> ncall );
89 } else {
90 printf( " %7.7s" , "" );
91 }
92 printf( " %s\n" , np -> name );
93}
94
95gprofheader()
96{
8b570c5c
PK
97
98 if ( bflag ) {
bc19d06b 99 printblurb( CALLG_BLURB );
8b570c5c 100 }
7ec9eedc
PK
101 printf( "\ngranularity: each sample hit covers %d byte(s)" ,
102 (long) scale * sizeof(UNIT) );
54c5b05a
PK
103 if ( printtime > 0.0 ) {
104 printf( " for %.2f%% of %.2f seconds\n\n" ,
89bcca98 105 100.0/printtime , printtime / hz );
54c5b05a
PK
106 } else {
107 printf( " no time propagated\n\n" );
108 /*
109 * this doesn't hurt, since all the numerators will be 0.0
110 */
111 printtime = 1.0;
112 }
68fa3db5
PK
113 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" ,
114 "" , "" , "" , "" , "called" , "total" , "parents" , "" );
115 printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
116 "index" , "%time" , "self" , "descendents" ,
117 "called" , "self" , "name" , "index" );
118 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" ,
119 "" , "" , "" , "" , "called" , "total" , "children" , "" );
120 printf( "\n" );
121}
122
123gprofline( np )
124 register nltype *np;
125{
126 char kirkbuffer[ BUFSIZ ];
127
128 sprintf( kirkbuffer , "[%d]" , np -> index );
129 printf( "%-6.6s %5.1f %7.2f %11.2f" ,
130 kirkbuffer ,
a441395b 131 100 * ( np -> propself + np -> propchild ) / printtime ,
89bcca98
PK
132 np -> propself / hz ,
133 np -> propchild / hz );
68fa3db5
PK
134 if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
135 printf( " %7d" , np -> ncall );
136 if ( np -> selfcalls != 0 ) {
137 printf( "+%-7d " , np -> selfcalls );
138 } else {
139 printf( " %7.7s " , "" );
140 }
141 } else {
142 printf( " %7.7s %7.7s " , "" , "" );
143 }
144 printname( np );
145 printf( "\n" );
146}
147
31f0a970 148printgprof()
873be5f6
PK
149{
150 nltype **timesortnlp;
151 int index;
152 nltype *parentp;
873be5f6
PK
153
154 /*
a441395b 155 * Now, sort by propself + propchild.
ad3b82ad
PK
156 * sorting both the regular function names
157 * and cycle headers.
873be5f6 158 */
ad3b82ad 159 timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
873be5f6 160 if ( timesortnlp == (nltype **) 0 ) {
ad3b82ad 161 fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
873be5f6 162 }
68fa3db5 163 for ( index = 0 ; index < nname ; index++ ) {
873be5f6
PK
164 timesortnlp[index] = &nl[index];
165 }
ad3b82ad
PK
166 for ( index = 1 ; index <= ncycle ; index++ ) {
167 timesortnlp[nname+index-1] = &cyclenl[index];
68fa3db5 168 }
ad3b82ad
PK
169 qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
170 for ( index = 0 ; index < nname + ncycle ; index++ ) {
873be5f6
PK
171 timesortnlp[ index ] -> index = index + 1;
172 }
173 /*
174 * Now, print out the structured profiling list
175 */
68fa3db5
PK
176 printf( "\f\n" );
177 gprofheader();
ad3b82ad 178 for ( index = 0 ; index < nname + ncycle ; index ++ ) {
873be5f6 179 parentp = timesortnlp[ index ];
8b570c5c 180 if ( zflag == 0 &&
873be5f6
PK
181 parentp -> ncall == 0 &&
182 parentp -> selfcalls == 0 &&
a441395b
PK
183 parentp -> propself == 0 &&
184 parentp -> propchild == 0 ) {
873be5f6
PK
185 continue;
186 }
7ec9eedc
PK
187 if ( ! parentp -> printflag ) {
188 continue;
189 }
873be5f6
PK
190 if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
191 /*
192 * cycle header
193 */
68fa3db5
PK
194 printcycle( parentp );
195 printmembers( parentp );
873be5f6
PK
196 } else {
197 printparents( parentp );
68fa3db5 198 gprofline( parentp );
873be5f6
PK
199 printchildren( parentp );
200 }
201 printf( "\n" );
68fa3db5
PK
202 printf( "-----------------------------------------------\n" );
203 printf( "\n" );
873be5f6 204 }
873be5f6
PK
205}
206
f3d4b802 207 /*
a441395b 208 * sort by decreasing propagated time
f3d4b802
PK
209 * if times are equal, but one is a cycle header,
210 * say that's first (e.g. less, i.e. -1).
211 * if one's name doesn't have an underscore and the other does,
212 * say the one is first.
213 * all else being equal, sort by names.
214 */
215int
216totalcmp( npp1 , npp2 )
217 nltype **npp1;
218 nltype **npp2;
219{
220 register nltype *np1 = *npp1;
221 register nltype *np2 = *npp2;
222 double diff;
223
a441395b
PK
224 diff = ( np1 -> propself + np1 -> propchild )
225 - ( np2 -> propself + np2 -> propchild );
f3d4b802
PK
226 if ( diff < 0.0 )
227 return 1;
228 if ( diff > 0.0 )
229 return -1;
230 if ( np1 -> name == 0 && np1 -> cycleno != 0 )
231 return -1;
232 if ( np2 -> name == 0 && np2 -> cycleno != 0 )
233 return 1;
234 if ( np1 -> name == 0 )
235 return -1;
236 if ( np2 -> name == 0 )
237 return 1;
238 if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
239 return -1;
240 if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
241 return 1;
a441395b
PK
242 if ( np1 -> ncall > np2 -> ncall )
243 return -1;
244 if ( np1 -> ncall < np2 -> ncall )
245 return 1;
f3d4b802
PK
246 return strcmp( np1 -> name , np2 -> name );
247}
248
873be5f6
PK
249printparents( childp )
250 nltype *childp;
251{
252 nltype *parentp;
253 arctype *arcp;
254 nltype *cycleheadp;
255
256 if ( childp -> cyclehead != 0 ) {
257 cycleheadp = childp -> cyclehead;
258 } else {
259 cycleheadp = childp;
260 }
261 if ( childp -> parents == 0 ) {
68fa3db5 262 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" ,
873be5f6
PK
263 "" , "" , "" , "" , "" , "" );
264 return;
265 }
266 sortparents( childp );
267 for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
268 parentp = arcp -> arc_parentp;
269 if ( childp == parentp ||
270 ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
271 /*
68fa3db5 272 * selfcall or call among siblings
873be5f6 273 */
68fa3db5 274 printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " ,
873be5f6
PK
275 "" , "" , "" , "" ,
276 arcp -> arc_count , "" );
277 printname( parentp );
278 printf( "\n" );
279 } else {
280 /*
281 * regular parent of child
282 */
68fa3db5
PK
283 printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " ,
284 "" , "" ,
89bcca98 285 arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
873be5f6
PK
286 arcp -> arc_count , cycleheadp -> ncall );
287 printname( parentp );
288 printf( "\n" );
289 }
290 }
291}
292
293printchildren( parentp )
294 nltype *parentp;
295{
296 nltype *childp;
297 arctype *arcp;
298
299 sortchildren( parentp );
300 arcp = parentp -> children;
301 for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
302 childp = arcp -> arc_childp;
303 if ( childp == parentp ||
304 ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
305 /*
306 * self call or call to sibling
307 */
68fa3db5
PK
308 printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " ,
309 "" , "" , "" , "" , arcp -> arc_count , "" );
873be5f6
PK
310 printname( childp );
311 printf( "\n" );
312 } else {
313 /*
314 * regular child of parent
315 */
68fa3db5
PK
316 printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " ,
317 "" , "" ,
89bcca98 318 arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
873be5f6
PK
319 arcp -> arc_count , childp -> cyclehead -> ncall );
320 printname( childp );
321 printf( "\n" );
322 }
323 }
324}
325
326printname( selfp )
327 nltype *selfp;
328{
329
330 if ( selfp -> name != 0 ) {
68fa3db5 331 printf( "%s" , selfp -> name );
873be5f6
PK
332# ifdef DEBUG
333 if ( debug & DFNDEBUG ) {
334 printf( "{%d} " , selfp -> toporder );
335 }
a441395b
PK
336 if ( debug & PROPDEBUG ) {
337 printf( "%5.2f%% " , selfp -> propfraction );
338 }
873be5f6
PK
339# endif DEBUG
340 }
341 if ( selfp -> cycleno != 0 ) {
f5ade73c
PK
342 printf( "\t<cycle %d>" , selfp -> cycleno );
343 }
344 if ( selfp -> index != 0 ) {
7ec9eedc
PK
345 if ( selfp -> printflag ) {
346 printf( " [%d]" , selfp -> index );
347 } else {
348 printf( " (%d)" , selfp -> index );
349 }
873be5f6
PK
350 }
351}
352
353sortchildren( parentp )
354 nltype *parentp;
355{
356 arctype *arcp;
357 arctype *detachedp;
358 arctype sorted;
359 arctype *prevp;
360
361 /*
362 * unlink children from parent,
363 * then insertion sort back on to sorted's children.
364 * *arcp the arc you have detached and are inserting.
365 * *detachedp the rest of the arcs to be sorted.
366 * sorted arc list onto which you insertion sort.
367 * *prevp arc before the arc you are comparing.
368 */
369 sorted.arc_childlist = 0;
370 for ( arcp = parentp -> children , detachedp = arcp -> arc_childlist ;
371 arcp ;
372 arcp = detachedp , detachedp = detachedp -> arc_childlist ) {
373 /*
374 * consider *arcp as disconnected
375 * insert it into sorted
376 */
377 for ( prevp = &sorted ;
378 prevp -> arc_childlist ;
379 prevp = prevp -> arc_childlist ) {
380 if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
381 break;
382 }
383 }
384 arcp -> arc_childlist = prevp -> arc_childlist;
385 prevp -> arc_childlist = arcp;
386 }
387 /*
388 * reattach sorted children to parent
389 */
390 parentp -> children = sorted.arc_childlist;
391}
392
393sortparents( childp )
394 nltype *childp;
395{
396 arctype *arcp;
397 arctype *detachedp;
398 arctype sorted;
399 arctype *prevp;
400
401 /*
402 * unlink parents from child,
403 * then insertion sort back on to sorted's parents.
404 * *arcp the arc you have detached and are inserting.
405 * *detachedp the rest of the arcs to be sorted.
406 * sorted arc list onto which you insertion sort.
407 * *prevp arc before the arc you are comparing.
408 */
409 sorted.arc_parentlist = 0;
410 for ( arcp = childp -> parents , detachedp = arcp -> arc_parentlist ;
411 arcp ;
412 arcp = detachedp , detachedp = detachedp -> arc_parentlist ) {
413 /*
414 * consider *arcp as disconnected
415 * insert it into sorted
416 */
417 for ( prevp = &sorted ;
418 prevp -> arc_parentlist ;
419 prevp = prevp -> arc_parentlist ) {
420 if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
421 break;
422 }
423 }
424 arcp -> arc_parentlist = prevp -> arc_parentlist;
425 prevp -> arc_parentlist = arcp;
426 }
427 /*
428 * reattach sorted arcs to child
429 */
430 childp -> parents = sorted.arc_parentlist;
431}
432
68fa3db5
PK
433 /*
434 * print a cycle header
435 */
436printcycle( cyclep )
437 nltype *cyclep;
438{
439 char kirkbuffer[ BUFSIZ ];
440
441 sprintf( kirkbuffer , "[%d]" , cyclep -> index );
442 printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
443 kirkbuffer ,
a441395b 444 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
89bcca98
PK
445 cyclep -> propself / hz ,
446 cyclep -> propchild / hz ,
68fa3db5
PK
447 cyclep -> ncall );
448 if ( cyclep -> selfcalls != 0 ) {
449 printf( "+%-7d" , cyclep -> selfcalls );
450 } else {
451 printf( " %7.7s" , "" );
452 }
453 printf( " <cycle %d as a whole>\t[%d]\n" ,
454 cyclep -> cycleno , cyclep -> index );
455}
456
457 /*
458 * print the members of a cycle
459 */
460printmembers( cyclep )
461 nltype *cyclep;
462{
463 nltype *memberp;
464
465 sortmembers( cyclep );
466 for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
467 printf( "%6.6s %5.5s %7.2f %11.2f %7d" ,
89bcca98 468 "" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
68fa3db5
PK
469 memberp -> ncall );
470 if ( memberp -> selfcalls != 0 ) {
471 printf( "+%-7d" , memberp -> selfcalls );
472 } else {
473 printf( " %7.7s" , "" );
474 }
475 printf( " " );
476 printname( memberp );
477 printf( "\n" );
478 }
479}
480
481 /*
482 * sort members of a cycle
483 */
484sortmembers( cyclep )
485 nltype *cyclep;
486{
487 nltype *todo;
488 nltype *doing;
489 nltype *prev;
490
491 /*
492 * detach cycle members from cyclehead,
493 * and insertion sort them back on.
494 */
495 todo = cyclep -> cnext;
496 cyclep -> cnext = 0;
497 for ( doing = todo , todo = doing -> cnext ;
498 doing ;
499 doing = todo , todo = doing -> cnext ) {
500 for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
501 if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
502 break;
503 }
504 }
505 doing -> cnext = prev -> cnext;
506 prev -> cnext = doing;
507 }
508}
509
510 /*
a441395b 511 * major sort is on propself + propchild,
68fa3db5
PK
512 * next is sort on ncalls + selfcalls.
513 */
f5ade73c 514int
68fa3db5
PK
515membercmp( this , that )
516 nltype *this;
517 nltype *that;
518{
a441395b
PK
519 double thistime = this -> propself + this -> propchild;
520 double thattime = that -> propself + that -> propchild;
68fa3db5
PK
521 long thiscalls = this -> ncall + this -> selfcalls;
522 long thatcalls = that -> ncall + that -> selfcalls;
523
524 if ( thistime > thattime ) {
525 return GREATERTHAN;
526 }
527 if ( thistime < thattime ) {
528 return LESSTHAN;
529 }
530 if ( thiscalls > thatcalls ) {
531 return GREATERTHAN;
532 }
533 if ( thiscalls < thatcalls ) {
534 return LESSTHAN;
535 }
536 return EQUALTO;
537}
873be5f6
PK
538 /*
539 * compare two arcs to/from the same child/parent.
540 * - if one arc is a self arc, it's least.
541 * - if one arc is within a cycle, it's less than.
542 * - if both arcs are within a cycle, compare arc counts.
543 * - if neither arc is within a cycle, compare with
a441395b 544 * arc_time + arc_childtime as major key
873be5f6
PK
545 * arc count as minor key
546 */
547int
548arccmp( thisp , thatp )
549 arctype *thisp;
550 arctype *thatp;
551{
552 nltype *thisparentp = thisp -> arc_parentp;
553 nltype *thischildp = thisp -> arc_childp;
554 nltype *thatparentp = thatp -> arc_parentp;
555 nltype *thatchildp = thatp -> arc_childp;
556 double thistime;
557 double thattime;
558
559# ifdef DEBUG
560 if ( debug & TIMEDEBUG ) {
561 printf( "[arccmp] " );
562 printname( thisparentp );
563 printf( " calls " );
564 printname ( thischildp );
565 printf( " %f + %f %d/%d\n" ,
566 thisp -> arc_time , thisp -> arc_childtime ,
567 thisp -> arc_count , thischildp -> ncall );
568 printf( "[arccmp] " );
569 printname( thatparentp );
570 printf( " calls " );
571 printname( thatchildp );
572 printf( " %f + %f %d/%d\n" ,
573 thatp -> arc_time , thatp -> arc_childtime ,
574 thatp -> arc_count , thatchildp -> ncall );
575 printf( "\n" );
576 }
577# endif DEBUG
578 if ( thisparentp == thischildp ) {
579 /* this is a self call */
580 return LESSTHAN;
581 }
582 if ( thatparentp == thatchildp ) {
583 /* that is a self call */
584 return GREATERTHAN;
585 }
586 if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
587 thisparentp -> cycleno == thischildp -> cycleno ) {
588 /* this is a call within a cycle */
589 if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
590 thatparentp -> cycleno == thatchildp -> cycleno ) {
591 /* that is a call within the cycle, too */
592 if ( thisp -> arc_count < thatp -> arc_count ) {
593 return LESSTHAN;
594 }
595 if ( thisp -> arc_count > thatp -> arc_count ) {
596 return GREATERTHAN;
597 }
598 return EQUALTO;
599 } else {
600 /* that isn't a call within the cycle */
601 return LESSTHAN;
602 }
603 } else {
604 /* this isn't a call within a cycle */
605 if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
606 thatparentp -> cycleno == thatchildp -> cycleno ) {
607 /* that is a call within a cycle */
608 return GREATERTHAN;
609 } else {
610 /* neither is a call within a cycle */
611 thistime = thisp -> arc_time + thisp -> arc_childtime;
612 thattime = thatp -> arc_time + thatp -> arc_childtime;
613 if ( thistime < thattime )
614 return LESSTHAN;
615 if ( thistime > thattime )
616 return GREATERTHAN;
617 if ( thisp -> arc_count < thatp -> arc_count )
618 return LESSTHAN;
619 if ( thisp -> arc_count > thatp -> arc_count )
620 return GREATERTHAN;
621 return EQUALTO;
622 }
623 }
624}
8b570c5c
PK
625
626printblurb( blurbname )
627 char *blurbname;
628{
8b570c5c
PK
629 FILE *blurbfile;
630 int input;
631
bc19d06b 632 blurbfile = fopen( blurbname , "r" );
8b570c5c 633 if ( blurbfile == NULL ) {
bc19d06b 634 perror( blurbname );
8b570c5c
PK
635 return;
636 }
637 while ( ( input = getc( blurbfile ) ) != EOF ) {
638 putchar( input );
639 }
640 fclose( blurbfile );
641}