|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)printgprof.c 1.14 (Berkeley) 3/30/83";
3: #endif lint
4:
5: #include "gprof.h"
6:
7: printprof()
8: {
9: register nltype *np;
10: nltype **sortednlp;
11: int index;
12:
13: printf( "\ngranularity: each sample hit covers %d byte(s)" ,
14: (long) scale * sizeof(UNIT) );
15: if ( totime > 0.0 ) {
16: printf( " for %.2f%% of %.2f seconds\n\n" ,
17: 100.0/totime , totime / hz );
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: }
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;
43: }
44:
45: timecmp( npp1 , npp2 )
46: nltype **npp1, **npp2;
47: {
48: double timediff;
49: long calldiff;
50:
51: timediff = (*npp2) -> time - (*npp1) -> time;
52: if ( timediff > 0.0 )
53: return 1 ;
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 )
60: return -1;
61: return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
62: }
63:
64: /*
65: * header for flatprofline
66: */
67: flatprofheader()
68: {
69:
70: if ( bflag ) {
71: printblurb( FLAT_BLURB );
72: }
73: printf( "%5.5s %7.7s %7.7s %7.7s %-8.8s\n" ,
74: "%time" , "cumsecs" , "seconds" , "calls" , "name" );
75: }
76:
77: flatprofline( np )
78: register nltype *np;
79: {
80:
81: if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
82: return;
83: }
84: actime += np -> time;
85: printf( "%5.1f %7.2f %7.2f" ,
86: 100 * np -> time / totime , actime / hz , np -> time / hz );
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:
95: gprofheader()
96: {
97:
98: if ( bflag ) {
99: printblurb( CALLG_BLURB );
100: }
101: printf( "\ngranularity: each sample hit covers %d byte(s)" ,
102: (long) scale * sizeof(UNIT) );
103: if ( printtime > 0.0 ) {
104: printf( " for %.2f%% of %.2f seconds\n\n" ,
105: 100.0/printtime , printtime / hz );
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: }
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:
123: gprofline( 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 ,
131: 100 * ( np -> propself + np -> propchild ) / printtime ,
132: np -> propself / hz ,
133: np -> propchild / hz );
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:
148: printgprof()
149: {
150: nltype **timesortnlp;
151: int index;
152: nltype *parentp;
153:
154: /*
155: * Now, sort by propself + propchild.
156: * sorting both the regular function names
157: * and cycle headers.
158: */
159: timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
160: if ( timesortnlp == (nltype **) 0 ) {
161: fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
162: }
163: for ( index = 0 ; index < nname ; index++ ) {
164: timesortnlp[index] = &nl[index];
165: }
166: for ( index = 1 ; index <= ncycle ; index++ ) {
167: timesortnlp[nname+index-1] = &cyclenl[index];
168: }
169: qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
170: for ( index = 0 ; index < nname + ncycle ; index++ ) {
171: timesortnlp[ index ] -> index = index + 1;
172: }
173: /*
174: * Now, print out the structured profiling list
175: */
176: printf( "\f\n" );
177: gprofheader();
178: for ( index = 0 ; index < nname + ncycle ; index ++ ) {
179: parentp = timesortnlp[ index ];
180: if ( zflag == 0 &&
181: parentp -> ncall == 0 &&
182: parentp -> selfcalls == 0 &&
183: parentp -> propself == 0 &&
184: parentp -> propchild == 0 ) {
185: continue;
186: }
187: if ( ! parentp -> printflag ) {
188: continue;
189: }
190: if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
191: /*
192: * cycle header
193: */
194: printcycle( parentp );
195: printmembers( parentp );
196: } else {
197: printparents( parentp );
198: gprofline( parentp );
199: printchildren( parentp );
200: }
201: printf( "\n" );
202: printf( "-----------------------------------------------\n" );
203: printf( "\n" );
204: }
205: }
206:
207: /*
208: * sort by decreasing propagated time
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: */
215: int
216: totalcmp( npp1 , npp2 )
217: nltype **npp1;
218: nltype **npp2;
219: {
220: register nltype *np1 = *npp1;
221: register nltype *np2 = *npp2;
222: double diff;
223:
224: diff = ( np1 -> propself + np1 -> propchild )
225: - ( np2 -> propself + np2 -> propchild );
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;
242: if ( np1 -> ncall > np2 -> ncall )
243: return -1;
244: if ( np1 -> ncall < np2 -> ncall )
245: return 1;
246: return strcmp( np1 -> name , np2 -> name );
247: }
248:
249: printparents( 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 ) {
262: printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" ,
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: /*
272: * selfcall or call among siblings
273: */
274: printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " ,
275: "" , "" , "" , "" ,
276: arcp -> arc_count , "" );
277: printname( parentp );
278: printf( "\n" );
279: } else {
280: /*
281: * regular parent of child
282: */
283: printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " ,
284: "" , "" ,
285: arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
286: arcp -> arc_count , cycleheadp -> ncall );
287: printname( parentp );
288: printf( "\n" );
289: }
290: }
291: }
292:
293: printchildren( 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: */
308: printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " ,
309: "" , "" , "" , "" , arcp -> arc_count , "" );
310: printname( childp );
311: printf( "\n" );
312: } else {
313: /*
314: * regular child of parent
315: */
316: printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " ,
317: "" , "" ,
318: arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
319: arcp -> arc_count , childp -> cyclehead -> ncall );
320: printname( childp );
321: printf( "\n" );
322: }
323: }
324: }
325:
326: printname( selfp )
327: nltype *selfp;
328: {
329:
330: if ( selfp -> name != 0 ) {
331: printf( "%s" , selfp -> name );
332: # ifdef DEBUG
333: if ( debug & DFNDEBUG ) {
334: printf( "{%d} " , selfp -> toporder );
335: }
336: if ( debug & PROPDEBUG ) {
337: printf( "%5.2f%% " , selfp -> propfraction );
338: }
339: # endif DEBUG
340: }
341: if ( selfp -> cycleno != 0 ) {
342: printf( "\t<cycle %d>" , selfp -> cycleno );
343: }
344: if ( selfp -> index != 0 ) {
345: if ( selfp -> printflag ) {
346: printf( " [%d]" , selfp -> index );
347: } else {
348: printf( " (%d)" , selfp -> index );
349: }
350: }
351: }
352:
353: sortchildren( 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:
393: sortparents( 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:
433: /*
434: * print a cycle header
435: */
436: printcycle( 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 ,
444: 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
445: cyclep -> propself / hz ,
446: cyclep -> propchild / hz ,
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: */
460: printmembers( 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" ,
468: "" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
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: */
484: sortmembers( 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: /*
511: * major sort is on propself + propchild,
512: * next is sort on ncalls + selfcalls.
513: */
514: int
515: membercmp( this , that )
516: nltype *this;
517: nltype *that;
518: {
519: double thistime = this -> propself + this -> propchild;
520: double thattime = that -> propself + that -> propchild;
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: }
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
544: * arc_time + arc_childtime as major key
545: * arc count as minor key
546: */
547: int
548: arccmp( 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: }
625:
626: printblurb( blurbname )
627: char *blurbname;
628: {
629: FILE *blurbfile;
630: int input;
631:
632: blurbfile = fopen( blurbname , "r" );
633: if ( blurbfile == NULL ) {
634: perror( blurbname );
635: return;
636: }
637: while ( ( input = getc( blurbfile ) ) != EOF ) {
638: putchar( input );
639: }
640: fclose( blurbfile );
641: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.