14515Speter #ifndef lint 2*4854Speter static char *sccsid = "@(#)printgprof.c 1.5 (Berkeley) 11/10/81"; 34515Speter #endif lint 44515Speter 54562Speter #include "gprof.h" 64515Speter 74753Speter printprof() 84753Speter { 94753Speter register nltype *np; 104753Speter nltype **sortednlp; 114753Speter int index; 124753Speter 13*4854Speter printf( "\ngranularity: each sample hit covers %d byte(s)" , (long) scale ); 14*4854Speter printf( " for %.2f%% of %.2f seconds\n\n" , 100.0/totime , totime / HZ ); 154753Speter actime = 0.0; 164753Speter flatprofheader(); 174753Speter /* 184753Speter * Sort the symbol table in by time 194753Speter */ 204753Speter sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); 214753Speter if ( sortednlp == (nltype **) 0 ) { 224753Speter fprintf( stderr , "[printprof] ran out of memory for time sorting\n" ); 234753Speter } 244753Speter for ( index = 0 ; index < nname ; index += 1 ) { 254753Speter sortednlp[ index ] = &nl[ index ]; 264753Speter } 274753Speter qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); 284753Speter for ( index = 0 ; index < nname ; index += 1 ) { 294753Speter np = sortednlp[ index ]; 304753Speter flatprofline( np ); 314753Speter } 324753Speter actime = 0.0; 334753Speter } 344753Speter 354753Speter timecmp( npp1 , npp2 ) 364753Speter nltype **npp1, **npp2; 374753Speter { 384753Speter double d; 394753Speter 404753Speter d = (*npp2) -> time - (*npp1) -> time; 414753Speter if ( d > 0.0 ) 424753Speter return 1 ; 434753Speter if ( d < 0.0 ) 444753Speter return -1; 454753Speter return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); 464753Speter } 474753Speter 484753Speter /* 494753Speter * header for flatprofline 504753Speter */ 514753Speter flatprofheader() 524753Speter { 534753Speter 54*4854Speter if ( bflag ) { 55*4854Speter printblurb( "flat.blurb" ); 56*4854Speter } 574753Speter printf( "%5.5s %7.7s %7.7s %7.7s %-8.8s\n" , 584753Speter "%time" , "cumsecs" , "seconds" , "calls" , "name" ); 594753Speter } 604753Speter 614753Speter flatprofline( np ) 624753Speter register nltype *np; 634753Speter { 644753Speter 65*4854Speter if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) { 664753Speter return; 674753Speter } 684753Speter actime += np -> time; 694753Speter printf( "%5.1f %7.2f %7.2f" , 704753Speter 100 * np -> time / totime , actime / HZ , np -> time / HZ ); 714753Speter if ( np -> ncall != 0 ) { 724753Speter printf( " %7d" , np -> ncall ); 734753Speter } else { 744753Speter printf( " %7.7s" , "" ); 754753Speter } 764753Speter printf( " %s\n" , np -> name ); 774753Speter } 784753Speter 794753Speter gprofheader() 804753Speter { 81*4854Speter 82*4854Speter if ( bflag ) { 83*4854Speter printblurb( "callg.blurb" ); 84*4854Speter } 854753Speter printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 864753Speter "" , "" , "" , "" , "called" , "total" , "parents" , "" ); 874753Speter printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , 884753Speter "index" , "%time" , "self" , "descendents" , 894753Speter "called" , "self" , "name" , "index" ); 904753Speter printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 914753Speter "" , "" , "" , "" , "called" , "total" , "children" , "" ); 924753Speter printf( "\n" ); 934753Speter } 944753Speter 954753Speter gprofline( np ) 964753Speter register nltype *np; 974753Speter { 984753Speter char kirkbuffer[ BUFSIZ ]; 994753Speter 1004753Speter sprintf( kirkbuffer , "[%d]" , np -> index ); 1014753Speter printf( "%-6.6s %5.1f %7.2f %11.2f" , 1024753Speter kirkbuffer , 1034753Speter 100 * ( np -> time + np -> childtime ) / totime , 1044753Speter np -> time / HZ , 1054753Speter np -> childtime / HZ ); 1064753Speter if ( ( np -> ncall + np -> selfcalls ) != 0 ) { 1074753Speter printf( " %7d" , np -> ncall ); 1084753Speter if ( np -> selfcalls != 0 ) { 1094753Speter printf( "+%-7d " , np -> selfcalls ); 1104753Speter } else { 1114753Speter printf( " %7.7s " , "" ); 1124753Speter } 1134753Speter } else { 1144753Speter printf( " %7.7s %7.7s " , "" , "" ); 1154753Speter } 1164753Speter printname( np ); 1174753Speter printf( "\n" ); 1184753Speter } 1194753Speter 1204562Speter printgprof() 1214515Speter { 1224515Speter nltype **timesortnlp; 1234515Speter int index; 1244515Speter nltype *parentp; 1254515Speter 1264515Speter /* 1274515Speter * Now, sort by time + childtime. 1284515Speter * include the cycle headers hiding out past nl[nname]. 1294753Speter * don't include the dummy hiding at nl[nname]. 1304515Speter */ 1314753Speter timesortnlp = (nltype **) calloc( nname + cyclemax , sizeof(nltype *) ); 1324515Speter if ( timesortnlp == (nltype **) 0 ) { 1334515Speter fprintf( stderr , "[doarcs] ran out of memory for sorting\n" ); 1344515Speter } 1354753Speter for ( index = 0 ; index < nname ; index++ ) { 1364515Speter timesortnlp[index] = &nl[index]; 1374515Speter } 1384753Speter for ( index = 1 ; index <= cyclemax ; index++ ) { 1394753Speter timesortnlp[(nname-1)+index] = &nl[nname+index]; 1404753Speter } 1414753Speter qsort( timesortnlp , nname + cyclemax , sizeof(nltype *) , totalcmp ); 1424753Speter for ( index = 0 ; index < nname + cyclemax ; index++ ) { 1434515Speter timesortnlp[ index ] -> index = index + 1; 1444515Speter } 1454515Speter /* 1464515Speter * Now, print out the structured profiling list 1474515Speter */ 1484753Speter printf( "\f\n" ); 1494753Speter gprofheader(); 1504753Speter for ( index = 0 ; index < nname + cyclemax ; index ++ ) { 1514515Speter parentp = timesortnlp[ index ]; 152*4854Speter if ( zflag == 0 && 1534515Speter parentp -> ncall == 0 && 1544515Speter parentp -> selfcalls == 0 && 1554515Speter parentp -> time == 0 && 1564515Speter parentp -> childtime == 0 ) { 1574515Speter continue; 1584515Speter } 1594515Speter if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { 1604515Speter /* 1614515Speter * cycle header 1624515Speter */ 1634753Speter printcycle( parentp ); 1644753Speter printmembers( parentp ); 1654515Speter } else { 1664515Speter printparents( parentp ); 1674753Speter gprofline( parentp ); 1684515Speter printchildren( parentp ); 1694515Speter } 1704515Speter printf( "\n" ); 1714753Speter printf( "-----------------------------------------------\n" ); 1724753Speter printf( "\n" ); 1734515Speter } 1744515Speter } 1754515Speter 1764515Speter printparents( childp ) 1774515Speter nltype *childp; 1784515Speter { 1794515Speter nltype *parentp; 1804515Speter arctype *arcp; 1814515Speter nltype *cycleheadp; 1824515Speter 1834515Speter if ( childp -> cyclehead != 0 ) { 1844515Speter cycleheadp = childp -> cyclehead; 1854515Speter } else { 1864515Speter cycleheadp = childp; 1874515Speter } 1884515Speter if ( childp -> parents == 0 ) { 1894753Speter printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" , 1904515Speter "" , "" , "" , "" , "" , "" ); 1914515Speter return; 1924515Speter } 1934515Speter sortparents( childp ); 1944515Speter for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { 1954515Speter parentp = arcp -> arc_parentp; 1964515Speter if ( childp == parentp || 1974515Speter ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { 1984515Speter /* 1994753Speter * selfcall or call among siblings 2004515Speter */ 2014753Speter printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , 2024515Speter "" , "" , "" , "" , 2034515Speter arcp -> arc_count , "" ); 2044515Speter printname( parentp ); 2054515Speter printf( "\n" ); 2064515Speter } else { 2074515Speter /* 2084515Speter * regular parent of child 2094515Speter */ 2104753Speter printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , 2114753Speter "" , "" , 2124515Speter arcp -> arc_time / HZ , arcp -> arc_childtime / HZ , 2134515Speter arcp -> arc_count , cycleheadp -> ncall ); 2144515Speter printname( parentp ); 2154515Speter printf( "\n" ); 2164515Speter } 2174515Speter } 2184515Speter } 2194515Speter 2204515Speter printchildren( parentp ) 2214515Speter nltype *parentp; 2224515Speter { 2234515Speter nltype *childp; 2244515Speter arctype *arcp; 2254515Speter 2264515Speter sortchildren( parentp ); 2274515Speter arcp = parentp -> children; 2284515Speter for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 2294515Speter childp = arcp -> arc_childp; 2304515Speter if ( childp == parentp || 2314515Speter ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { 2324515Speter /* 2334515Speter * self call or call to sibling 2344515Speter */ 2354753Speter printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , 2364753Speter "" , "" , "" , "" , arcp -> arc_count , "" ); 2374515Speter printname( childp ); 2384515Speter printf( "\n" ); 2394515Speter } else { 2404515Speter /* 2414515Speter * regular child of parent 2424515Speter */ 2434753Speter printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , 2444753Speter "" , "" , 2454515Speter arcp -> arc_time / HZ , arcp -> arc_childtime / HZ , 2464515Speter arcp -> arc_count , childp -> cyclehead -> ncall ); 2474515Speter printname( childp ); 2484515Speter printf( "\n" ); 2494515Speter } 2504515Speter } 2514515Speter } 2524515Speter 2534515Speter printname( selfp ) 2544515Speter nltype *selfp; 2554515Speter { 2564515Speter 2574515Speter if ( selfp -> name != 0 ) { 2584753Speter printf( "%s" , selfp -> name ); 2594515Speter # ifdef DEBUG 2604515Speter if ( debug & DFNDEBUG ) { 2614515Speter printf( "{%d} " , selfp -> toporder ); 2624515Speter } 2634515Speter # endif DEBUG 2644515Speter } 2654842Speter if ( selfp -> cycleno != 0 ) { 2664842Speter printf( "\t<cycle %d>" , selfp -> cycleno ); 2674842Speter } 2684753Speter if ( selfp -> index != 0 ) { 2694842Speter printf( " [%d]" , selfp -> index ); 2704753Speter } 2714515Speter } 2724515Speter 2734515Speter sortchildren( parentp ) 2744515Speter nltype *parentp; 2754515Speter { 2764515Speter arctype *arcp; 2774515Speter arctype *detachedp; 2784515Speter arctype sorted; 2794515Speter arctype *prevp; 2804515Speter 2814515Speter /* 2824515Speter * unlink children from parent, 2834515Speter * then insertion sort back on to sorted's children. 2844515Speter * *arcp the arc you have detached and are inserting. 2854515Speter * *detachedp the rest of the arcs to be sorted. 2864515Speter * sorted arc list onto which you insertion sort. 2874515Speter * *prevp arc before the arc you are comparing. 2884515Speter */ 2894515Speter sorted.arc_childlist = 0; 2904515Speter for ( arcp = parentp -> children , detachedp = arcp -> arc_childlist ; 2914515Speter arcp ; 2924515Speter arcp = detachedp , detachedp = detachedp -> arc_childlist ) { 2934515Speter /* 2944515Speter * consider *arcp as disconnected 2954515Speter * insert it into sorted 2964515Speter */ 2974515Speter for ( prevp = &sorted ; 2984515Speter prevp -> arc_childlist ; 2994515Speter prevp = prevp -> arc_childlist ) { 3004515Speter if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) { 3014515Speter break; 3024515Speter } 3034515Speter } 3044515Speter arcp -> arc_childlist = prevp -> arc_childlist; 3054515Speter prevp -> arc_childlist = arcp; 3064515Speter } 3074515Speter /* 3084515Speter * reattach sorted children to parent 3094515Speter */ 3104515Speter parentp -> children = sorted.arc_childlist; 3114515Speter } 3124515Speter 3134515Speter sortparents( childp ) 3144515Speter nltype *childp; 3154515Speter { 3164515Speter arctype *arcp; 3174515Speter arctype *detachedp; 3184515Speter arctype sorted; 3194515Speter arctype *prevp; 3204515Speter 3214515Speter /* 3224515Speter * unlink parents from child, 3234515Speter * then insertion sort back on to sorted's parents. 3244515Speter * *arcp the arc you have detached and are inserting. 3254515Speter * *detachedp the rest of the arcs to be sorted. 3264515Speter * sorted arc list onto which you insertion sort. 3274515Speter * *prevp arc before the arc you are comparing. 3284515Speter */ 3294515Speter sorted.arc_parentlist = 0; 3304515Speter for ( arcp = childp -> parents , detachedp = arcp -> arc_parentlist ; 3314515Speter arcp ; 3324515Speter arcp = detachedp , detachedp = detachedp -> arc_parentlist ) { 3334515Speter /* 3344515Speter * consider *arcp as disconnected 3354515Speter * insert it into sorted 3364515Speter */ 3374515Speter for ( prevp = &sorted ; 3384515Speter prevp -> arc_parentlist ; 3394515Speter prevp = prevp -> arc_parentlist ) { 3404515Speter if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) { 3414515Speter break; 3424515Speter } 3434515Speter } 3444515Speter arcp -> arc_parentlist = prevp -> arc_parentlist; 3454515Speter prevp -> arc_parentlist = arcp; 3464515Speter } 3474515Speter /* 3484515Speter * reattach sorted arcs to child 3494515Speter */ 3504515Speter childp -> parents = sorted.arc_parentlist; 3514515Speter } 3524515Speter 3534515Speter /* 3544753Speter * print a cycle header 3554753Speter */ 3564753Speter printcycle( cyclep ) 3574753Speter nltype *cyclep; 3584753Speter { 3594753Speter char kirkbuffer[ BUFSIZ ]; 3604753Speter 3614753Speter sprintf( kirkbuffer , "[%d]" , cyclep -> index ); 3624753Speter printf( "%-6.6s %5.1f %7.2f %11.2f %7d" , 3634753Speter kirkbuffer , 3644753Speter 100 * ( cyclep -> time + cyclep -> childtime ) / totime , 3654753Speter cyclep -> time / HZ , 3664753Speter cyclep -> childtime / HZ , 3674753Speter cyclep -> ncall ); 3684753Speter if ( cyclep -> selfcalls != 0 ) { 3694753Speter printf( "+%-7d" , cyclep -> selfcalls ); 3704753Speter } else { 3714753Speter printf( " %7.7s" , "" ); 3724753Speter } 3734753Speter printf( " <cycle %d as a whole>\t[%d]\n" , 3744753Speter cyclep -> cycleno , cyclep -> index ); 3754753Speter } 3764753Speter 3774753Speter /* 3784753Speter * print the members of a cycle 3794753Speter */ 3804753Speter printmembers( cyclep ) 3814753Speter nltype *cyclep; 3824753Speter { 3834753Speter nltype *memberp; 3844753Speter 3854753Speter sortmembers( cyclep ); 3864753Speter for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { 3874753Speter printf( "%6.6s %5.5s %7.2f %11.2f %7d" , 3884753Speter "" , "" , memberp -> time / HZ , memberp -> childtime / HZ , 3894753Speter memberp -> ncall ); 3904753Speter if ( memberp -> selfcalls != 0 ) { 3914753Speter printf( "+%-7d" , memberp -> selfcalls ); 3924753Speter } else { 3934753Speter printf( " %7.7s" , "" ); 3944753Speter } 3954753Speter printf( " " ); 3964753Speter printname( memberp ); 3974753Speter printf( "\n" ); 3984753Speter } 3994753Speter } 4004753Speter 4014753Speter /* 4024753Speter * sort members of a cycle 4034753Speter */ 4044753Speter sortmembers( cyclep ) 4054753Speter nltype *cyclep; 4064753Speter { 4074753Speter nltype *todo; 4084753Speter nltype *doing; 4094753Speter nltype *prev; 4104753Speter 4114753Speter /* 4124753Speter * detach cycle members from cyclehead, 4134753Speter * and insertion sort them back on. 4144753Speter */ 4154753Speter todo = cyclep -> cnext; 4164753Speter cyclep -> cnext = 0; 4174753Speter for ( doing = todo , todo = doing -> cnext ; 4184753Speter doing ; 4194753Speter doing = todo , todo = doing -> cnext ) { 4204753Speter for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { 4214753Speter if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { 4224753Speter break; 4234753Speter } 4244753Speter } 4254753Speter doing -> cnext = prev -> cnext; 4264753Speter prev -> cnext = doing; 4274753Speter } 4284753Speter } 4294753Speter 4304753Speter /* 4314753Speter * major sort is on time + childtime, 4324753Speter * next is sort on ncalls + selfcalls. 4334753Speter */ 4344842Speter int 4354753Speter membercmp( this , that ) 4364753Speter nltype *this; 4374753Speter nltype *that; 4384753Speter { 4394753Speter double thistime = this -> time + this -> childtime; 4404753Speter double thattime = that -> time + that -> childtime; 4414753Speter long thiscalls = this -> ncall + this -> selfcalls; 4424753Speter long thatcalls = that -> ncall + that -> selfcalls; 4434753Speter 4444753Speter if ( thistime > thattime ) { 4454753Speter return GREATERTHAN; 4464753Speter } 4474753Speter if ( thistime < thattime ) { 4484753Speter return LESSTHAN; 4494753Speter } 4504753Speter if ( thiscalls > thatcalls ) { 4514753Speter return GREATERTHAN; 4524753Speter } 4534753Speter if ( thiscalls < thatcalls ) { 4544753Speter return LESSTHAN; 4554753Speter } 4564753Speter return EQUALTO; 4574753Speter } 4584753Speter /* 4594515Speter * compare two arcs to/from the same child/parent. 4604515Speter * - if one arc is a self arc, it's least. 4614515Speter * - if one arc is within a cycle, it's less than. 4624515Speter * - if both arcs are within a cycle, compare arc counts. 4634515Speter * - if neither arc is within a cycle, compare with 4644515Speter * time + childtime as major key 4654515Speter * arc count as minor key 4664515Speter */ 4674515Speter int 4684515Speter arccmp( thisp , thatp ) 4694515Speter arctype *thisp; 4704515Speter arctype *thatp; 4714515Speter { 4724515Speter nltype *thisparentp = thisp -> arc_parentp; 4734515Speter nltype *thischildp = thisp -> arc_childp; 4744515Speter nltype *thatparentp = thatp -> arc_parentp; 4754515Speter nltype *thatchildp = thatp -> arc_childp; 4764515Speter double thistime; 4774515Speter double thattime; 4784515Speter 4794515Speter # ifdef DEBUG 4804515Speter if ( debug & TIMEDEBUG ) { 4814515Speter printf( "[arccmp] " ); 4824515Speter printname( thisparentp ); 4834515Speter printf( " calls " ); 4844515Speter printname ( thischildp ); 4854515Speter printf( " %f + %f %d/%d\n" , 4864515Speter thisp -> arc_time , thisp -> arc_childtime , 4874515Speter thisp -> arc_count , thischildp -> ncall ); 4884515Speter printf( "[arccmp] " ); 4894515Speter printname( thatparentp ); 4904515Speter printf( " calls " ); 4914515Speter printname( thatchildp ); 4924515Speter printf( " %f + %f %d/%d\n" , 4934515Speter thatp -> arc_time , thatp -> arc_childtime , 4944515Speter thatp -> arc_count , thatchildp -> ncall ); 4954515Speter printf( "\n" ); 4964515Speter } 4974515Speter # endif DEBUG 4984515Speter if ( thisparentp == thischildp ) { 4994515Speter /* this is a self call */ 5004515Speter return LESSTHAN; 5014515Speter } 5024515Speter if ( thatparentp == thatchildp ) { 5034515Speter /* that is a self call */ 5044515Speter return GREATERTHAN; 5054515Speter } 5064515Speter if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && 5074515Speter thisparentp -> cycleno == thischildp -> cycleno ) { 5084515Speter /* this is a call within a cycle */ 5094515Speter if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 5104515Speter thatparentp -> cycleno == thatchildp -> cycleno ) { 5114515Speter /* that is a call within the cycle, too */ 5124515Speter if ( thisp -> arc_count < thatp -> arc_count ) { 5134515Speter return LESSTHAN; 5144515Speter } 5154515Speter if ( thisp -> arc_count > thatp -> arc_count ) { 5164515Speter return GREATERTHAN; 5174515Speter } 5184515Speter return EQUALTO; 5194515Speter } else { 5204515Speter /* that isn't a call within the cycle */ 5214515Speter return LESSTHAN; 5224515Speter } 5234515Speter } else { 5244515Speter /* this isn't a call within a cycle */ 5254515Speter if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 5264515Speter thatparentp -> cycleno == thatchildp -> cycleno ) { 5274515Speter /* that is a call within a cycle */ 5284515Speter return GREATERTHAN; 5294515Speter } else { 5304515Speter /* neither is a call within a cycle */ 5314515Speter thistime = thisp -> arc_time + thisp -> arc_childtime; 5324515Speter thattime = thatp -> arc_time + thatp -> arc_childtime; 5334515Speter if ( thistime < thattime ) 5344515Speter return LESSTHAN; 5354515Speter if ( thistime > thattime ) 5364515Speter return GREATERTHAN; 5374515Speter if ( thisp -> arc_count < thatp -> arc_count ) 5384515Speter return LESSTHAN; 5394515Speter if ( thisp -> arc_count > thatp -> arc_count ) 5404515Speter return GREATERTHAN; 5414515Speter return EQUALTO; 5424515Speter } 5434515Speter } 5444515Speter } 545*4854Speter 546*4854Speter printblurb( blurbname ) 547*4854Speter char *blurbname; 548*4854Speter { 549*4854Speter char pathname[ BUFSIZ ]; 550*4854Speter FILE *blurbfile; 551*4854Speter int input; 552*4854Speter 553*4854Speter # ifndef BLURBLIB 554*4854Speter # define BLURBLIB "./" 555*4854Speter # endif not BLURBLIB 556*4854Speter sprintf( pathname , "%s%s" , BLURBLIB , blurbname ); 557*4854Speter blurbfile = fopen( pathname , "r" ); 558*4854Speter if ( blurbfile == NULL ) { 559*4854Speter perror( pathname ); 560*4854Speter return; 561*4854Speter } 562*4854Speter while ( ( input = getc( blurbfile ) ) != EOF ) { 563*4854Speter putchar( input ); 564*4854Speter } 565*4854Speter fclose( blurbfile ); 566*4854Speter } 567