X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/8b570c5ca179fe7ad1198a7b8eada974bf1b05b1..4ad36dea8ce2cef4c5da044585a270d318a529d6:/usr/src/usr.bin/gprof/printgprof.c diff --git a/usr/src/usr.bin/gprof/printgprof.c b/usr/src/usr.bin/gprof/printgprof.c index 1f4b83ff20..f68432b8a2 100644 --- a/usr/src/usr.bin/gprof/printgprof.c +++ b/usr/src/usr.bin/gprof/printgprof.c @@ -1,6 +1,23 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + #ifndef lint - static char *sccsid = "@(#)printgprof.c 1.5 (Berkeley) %G%"; -#endif lint +static char sccsid[] = "@(#)printgprof.c 5.5 (Berkeley) %G%"; +#endif /* not lint */ #include "gprof.h" @@ -8,11 +25,10 @@ printprof() { register nltype *np; nltype **sortednlp; - int index; + int index, timecmp(); - printf( "\ngranularity: each sample hit covers %d byte(s)" , (long) scale ); - printf( " for %.2f%% of %.2f seconds\n\n" , 100.0/totime , totime / HZ ); actime = 0.0; + printf( "\f\n" ); flatprofheader(); /* * Sort the symbol table in by time @@ -30,17 +46,24 @@ printprof() flatprofline( np ); } actime = 0.0; + cfree( sortednlp ); } timecmp( npp1 , npp2 ) nltype **npp1, **npp2; { - double d; + double timediff; + long calldiff; - d = (*npp2) -> time - (*npp1) -> time; - if ( d > 0.0 ) + timediff = (*npp2) -> time - (*npp1) -> time; + if ( timediff > 0.0 ) return 1 ; - if ( d < 0.0 ) + if ( timediff < 0.0 ) + return -1; + calldiff = (*npp2) -> ncall - (*npp1) -> ncall; + if ( calldiff > 0 ) + return 1; + if ( calldiff < 0 ) return -1; return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); } @@ -52,10 +75,25 @@ flatprofheader() { if ( bflag ) { - printblurb( "flat.blurb" ); + printblurb( FLAT_BLURB ); + } + printf( "\ngranularity: each sample hit covers %d byte(s)" , + (long) scale * sizeof(UNIT) ); + if ( totime > 0.0 ) { + printf( " for %.2f%% of %.2f seconds\n\n" , + 100.0/totime , totime / hz ); + } else { + printf( " no time accumulated\n\n" ); + /* + * this doesn't hurt sinc eall the numerators will be zero. + */ + totime = 1.0; } - printf( "%5.5s %7.7s %7.7s %7.7s %-8.8s\n" , - "%time" , "cumsecs" , "seconds" , "calls" , "name" ); + printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , + "% " , "cumulative" , "self " , "" , "self " , "total " , "" ); + printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , + "time" , "seconds " , "seconds" , "calls" , + "ms/call" , "ms/call" , "name" ); } flatprofline( np ) @@ -66,29 +104,44 @@ flatprofline( np ) return; } actime += np -> time; - printf( "%5.1f %7.2f %7.2f" , - 100 * np -> time / totime , actime / HZ , np -> time / HZ ); + printf( "%5.1f %10.2f %8.2f" , + 100 * np -> time / totime , actime / hz , np -> time / hz ); if ( np -> ncall != 0 ) { - printf( " %7d" , np -> ncall ); + printf( " %8d %8.2f %8.2f " , np -> ncall , + 1000 * np -> time / hz / np -> ncall , + 1000 * ( np -> time + np -> childtime ) / hz / np -> ncall ); } else { - printf( " %7.7s" , "" ); + printf( " %8.8s %8.8s %8.8s " , "" , "" , "" ); } - printf( " %s\n" , np -> name ); + printname( np ); + printf( "\n" ); } gprofheader() { if ( bflag ) { - printblurb( "callg.blurb" ); + printblurb( CALLG_BLURB ); + } + printf( "\ngranularity: each sample hit covers %d byte(s)" , + (long) scale * sizeof(UNIT) ); + if ( printtime > 0.0 ) { + printf( " for %.2f%% of %.2f seconds\n\n" , + 100.0/printtime , printtime / hz ); + } else { + printf( " no time propagated\n\n" ); + /* + * this doesn't hurt, since all the numerators will be 0.0 + */ + printtime = 1.0; } printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , - "" , "" , "" , "" , "called" , "total" , "parents" , "" ); + "" , "" , "" , "" , "called" , "total" , "parents"); printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , "index" , "%time" , "self" , "descendents" , "called" , "self" , "name" , "index" ); printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , - "" , "" , "" , "" , "called" , "total" , "children" , "" ); + "" , "" , "" , "" , "called" , "total" , "children"); printf( "\n" ); } @@ -100,9 +153,9 @@ gprofline( np ) sprintf( kirkbuffer , "[%d]" , np -> index ); printf( "%-6.6s %5.1f %7.2f %11.2f" , kirkbuffer , - 100 * ( np -> time + np -> childtime ) / totime , - np -> time / HZ , - np -> childtime / HZ ); + 100 * ( np -> propself + np -> propchild ) / printtime , + np -> propself / hz , + np -> propchild / hz ); if ( ( np -> ncall + np -> selfcalls ) != 0 ) { printf( " %7d" , np -> ncall ); if ( np -> selfcalls != 0 ) { @@ -117,43 +170,26 @@ gprofline( np ) printf( "\n" ); } -printgprof() -{ +printgprof(timesortnlp) nltype **timesortnlp; +{ int index; nltype *parentp; /* - * Now, sort by time + childtime. - * include the cycle headers hiding out past nl[nname]. - * don't include the dummy hiding at nl[nname]. - */ - timesortnlp = (nltype **) calloc( nname + cyclemax , sizeof(nltype *) ); - if ( timesortnlp == (nltype **) 0 ) { - fprintf( stderr , "[doarcs] ran out of memory for sorting\n" ); - } - for ( index = 0 ; index < nname ; index++ ) { - timesortnlp[index] = &nl[index]; - } - for ( index = 1 ; index <= cyclemax ; index++ ) { - timesortnlp[(nname-1)+index] = &nl[nname+index]; - } - qsort( timesortnlp , nname + cyclemax , sizeof(nltype *) , totalcmp ); - for ( index = 0 ; index < nname + cyclemax ; index++ ) { - timesortnlp[ index ] -> index = index + 1; - } - /* - * Now, print out the structured profiling list + * Print out the structured profiling list */ - printf( "\f\n" ); gprofheader(); - for ( index = 0 ; index < nname + cyclemax ; index ++ ) { + for ( index = 0 ; index < nname + ncycle ; index ++ ) { parentp = timesortnlp[ index ]; if ( zflag == 0 && parentp -> ncall == 0 && parentp -> selfcalls == 0 && - parentp -> time == 0 && - parentp -> childtime == 0 ) { + parentp -> propself == 0 && + parentp -> propchild == 0 ) { + continue; + } + if ( ! parentp -> printflag ) { continue; } if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { @@ -171,6 +207,49 @@ printgprof() printf( "-----------------------------------------------\n" ); printf( "\n" ); } + cfree( timesortnlp ); +} + + /* + * sort by decreasing propagated time + * if times are equal, but one is a cycle header, + * say that's first (e.g. less, i.e. -1). + * if one's name doesn't have an underscore and the other does, + * say the one is first. + * all else being equal, sort by names. + */ +int +totalcmp( npp1 , npp2 ) + nltype **npp1; + nltype **npp2; +{ + register nltype *np1 = *npp1; + register nltype *np2 = *npp2; + double diff; + + diff = ( np1 -> propself + np1 -> propchild ) + - ( np2 -> propself + np2 -> propchild ); + if ( diff < 0.0 ) + return 1; + if ( diff > 0.0 ) + return -1; + if ( np1 -> name == 0 && np1 -> cycleno != 0 ) + return -1; + if ( np2 -> name == 0 && np2 -> cycleno != 0 ) + return 1; + if ( np1 -> name == 0 ) + return -1; + if ( np2 -> name == 0 ) + return 1; + if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' ) + return -1; + if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' ) + return 1; + if ( np1 -> ncall > np2 -> ncall ) + return -1; + if ( np1 -> ncall < np2 -> ncall ) + return 1; + return strcmp( np1 -> name , np2 -> name ); } printparents( childp ) @@ -209,7 +288,7 @@ printparents( childp ) */ printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , "" , "" , - arcp -> arc_time / HZ , arcp -> arc_childtime / HZ , + arcp -> arc_time / hz , arcp -> arc_childtime / hz , arcp -> arc_count , cycleheadp -> ncall ); printname( parentp ); printf( "\n" ); @@ -242,7 +321,7 @@ printchildren( parentp ) */ printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , "" , "" , - arcp -> arc_time / HZ , arcp -> arc_childtime / HZ , + arcp -> arc_time / hz , arcp -> arc_childtime / hz , arcp -> arc_count , childp -> cyclehead -> ncall ); printname( childp ); printf( "\n" ); @@ -260,13 +339,20 @@ printname( selfp ) if ( debug & DFNDEBUG ) { printf( "{%d} " , selfp -> toporder ); } + if ( debug & PROPDEBUG ) { + printf( "%5.2f%% " , selfp -> propfraction ); + } # endif DEBUG } if ( selfp -> cycleno != 0 ) { - printf( "\t" , selfp -> cycleno ); + printf( " " , selfp -> cycleno ); } if ( selfp -> index != 0 ) { - printf( " [%d]" , selfp -> index ); + if ( selfp -> printflag ) { + printf( " [%d]" , selfp -> index ); + } else { + printf( " (%d)" , selfp -> index ); + } } } @@ -287,9 +373,9 @@ sortchildren( parentp ) * *prevp arc before the arc you are comparing. */ sorted.arc_childlist = 0; - for ( arcp = parentp -> children , detachedp = arcp -> arc_childlist ; + for ( (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist); arcp ; - arcp = detachedp , detachedp = detachedp -> arc_childlist ) { + (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) { /* * consider *arcp as disconnected * insert it into sorted @@ -327,9 +413,9 @@ sortparents( childp ) * *prevp arc before the arc you are comparing. */ sorted.arc_parentlist = 0; - for ( arcp = childp -> parents , detachedp = arcp -> arc_parentlist ; + for ( (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist); arcp ; - arcp = detachedp , detachedp = detachedp -> arc_parentlist ) { + (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) { /* * consider *arcp as disconnected * insert it into sorted @@ -361,9 +447,9 @@ printcycle( cyclep ) sprintf( kirkbuffer , "[%d]" , cyclep -> index ); printf( "%-6.6s %5.1f %7.2f %11.2f %7d" , kirkbuffer , - 100 * ( cyclep -> time + cyclep -> childtime ) / totime , - cyclep -> time / HZ , - cyclep -> childtime / HZ , + 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime , + cyclep -> propself / hz , + cyclep -> propchild / hz , cyclep -> ncall ); if ( cyclep -> selfcalls != 0 ) { printf( "+%-7d" , cyclep -> selfcalls ); @@ -385,7 +471,7 @@ printmembers( cyclep ) sortmembers( cyclep ); for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { printf( "%6.6s %5.5s %7.2f %11.2f %7d" , - "" , "" , memberp -> time / HZ , memberp -> childtime / HZ , + "" , "" , memberp -> propself / hz , memberp -> propchild / hz , memberp -> ncall ); if ( memberp -> selfcalls != 0 ) { printf( "+%-7d" , memberp -> selfcalls ); @@ -414,9 +500,9 @@ sortmembers( cyclep ) */ todo = cyclep -> cnext; cyclep -> cnext = 0; - for ( doing = todo , todo = doing -> cnext ; + for ( (doing = todo)&&(todo = doing -> cnext); doing ; - doing = todo , todo = doing -> cnext ) { + (doing = todo )&&(todo = doing -> cnext )){ for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { break; @@ -428,7 +514,7 @@ sortmembers( cyclep ) } /* - * major sort is on time + childtime, + * major sort is on propself + propchild, * next is sort on ncalls + selfcalls. */ int @@ -436,8 +522,8 @@ membercmp( this , that ) nltype *this; nltype *that; { - double thistime = this -> time + this -> childtime; - double thattime = that -> time + that -> childtime; + double thistime = this -> propself + this -> propchild; + double thattime = that -> propself + that -> propchild; long thiscalls = this -> ncall + this -> selfcalls; long thatcalls = that -> ncall + that -> selfcalls; @@ -461,7 +547,7 @@ membercmp( this , that ) * - if one arc is within a cycle, it's less than. * - if both arcs are within a cycle, compare arc counts. * - if neither arc is within a cycle, compare with - * time + childtime as major key + * arc_time + arc_childtime as major key * arc count as minor key */ int @@ -546,17 +632,12 @@ arccmp( thisp , thatp ) printblurb( blurbname ) char *blurbname; { - char pathname[ BUFSIZ ]; FILE *blurbfile; int input; -# ifndef BLURBLIB -# define BLURBLIB "./" -# endif not BLURBLIB - sprintf( pathname , "%s%s" , BLURBLIB , blurbname ); - blurbfile = fopen( pathname , "r" ); + blurbfile = fopen( blurbname , "r" ); if ( blurbfile == NULL ) { - perror( pathname ); + perror( blurbname ); return; } while ( ( input = getc( blurbfile ) ) != EOF ) { @@ -564,3 +645,57 @@ printblurb( blurbname ) } fclose( blurbfile ); } + +int +namecmp( npp1 , npp2 ) + nltype **npp1, **npp2; +{ + return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); +} + +printindex() +{ + nltype **namesortnlp; + register nltype *nlp; + int index, nnames, todo, i, j; + char peterbuffer[ BUFSIZ ]; + + /* + * Now, sort regular function name alphbetically + * to create an index. + */ + namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); + if ( namesortnlp == (nltype **) 0 ) { + fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); + } + for ( index = 0 , nnames = 0 ; index < nname ; index++ ) { + if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 ) + continue; + namesortnlp[nnames++] = &nl[index]; + } + qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp ); + for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) { + namesortnlp[todo++] = &cyclenl[index]; + } + printf( "\f\nIndex by function name\n\n" ); + index = ( todo + 2 ) / 3; + for ( i = 0; i < index ; i++ ) { + for ( j = i; j < todo ; j += index ) { + nlp = namesortnlp[ j ]; + if ( nlp -> printflag ) { + sprintf( peterbuffer , "[%d]" , nlp -> index ); + } else { + sprintf( peterbuffer , "(%d)" , nlp -> index ); + } + if ( j < nnames ) { + printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name ); + } else { + printf( "%6.6s " , peterbuffer ); + sprintf( peterbuffer , "" , nlp -> cycleno ); + printf( "%-19.19s" , peterbuffer ); + } + } + printf( "\n" ); + } + cfree( namesortnlp ); +}