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