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