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