#include <stdlib.h>
#include "gprof.h"
#include "stuff/errors.h"
static int timecmp(
nltype **npp1,
nltype **npp2);
static void flatprofheader(
void);
static void flatprofline(
nltype *np);
static void gprofheader(
void);
static void gprofline(
nltype *np);
static void printparents(
nltype *childp);
static void printchildren(
nltype *parentp);
static void sortchildren(
nltype *parentp);
static void sortparents(
nltype *childp);
static void printcycle(
nltype *cyclep);
static void printmembers(
nltype *cyclep);
static void sortmembers(
nltype *cyclep);
static int membercmp(
nltype *this,
nltype *that);
static int arccmp(
arctype *thisp,
arctype *thatp);
static void printblurb(
char *blurbname);
static int namecmp(
nltype **npp1,
nltype **npp2);
void
printprof(
void)
{
nltype *np;
nltype **sortednlp;
unsigned long index;
actime = 0.0;
printf("\f\n");
flatprofheader();
sortednlp = (nltype **)calloc(nname, sizeof(nltype *));
if(sortednlp == (nltype **)0)
fatal("[printprof] ran out of memory for time sorting");
for(index = 0; index < nname; index += 1){
sortednlp[index] = &nl[index];
}
qsort(sortednlp, nname, sizeof(nltype *),
(int (*)(const void *, const void *))timecmp);
for(index = 0; index < nname; index += 1){
np = sortednlp[index];
flatprofline(np);
}
actime = 0.0;
free(sortednlp);
}
static
int
timecmp(
nltype **npp1,
nltype **npp2)
{
double timediff;
long calldiff;
timediff = (*npp2)->time - (*npp1)->time;
if(timediff > 0.0)
return(1);
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));
}
static
void
flatprofheader(
void)
{
if(bflag == TRUE){
printblurb(FLAT_BLURB);
}
printf("\ngranularity: each sample hit covers %lu byte(s)",
(long)sample_sets->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");
totime = 1.0;
}
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");
}
static
void
flatprofline(
nltype *np)
{
if(zflag == FALSE && np->ncall == 0 && np->time == 0){
return;
}
actime += np->time;
printf("%5.1f %10.2f %8.2f",
100 * np->time / totime, actime / hz, np->time / hz);
if(np->ncall != 0){
printf(" %8ld %8.2f %8.2f ", np->ncall,
1000 * np->time / hz / np->ncall,
1000 * (np->time + np->childtime) / hz / np->ncall);
}
else{
printf(" %8.8s %8.8s %8.8s ", "", "", "");
}
printname(np);
printf("\n");
}
static
void
gprofheader(
void)
{
if(bflag == TRUE){
printblurb(CALLG_BLURB);
}
printf("\ngranularity: each sample hit covers %lu byte(s)",
(long)sample_sets->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");
printtime = 1.0;
}
printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
"", "", "", "", "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");
printf("\n");
}
static
void
gprofline(
nltype *np)
{
char kirkbuffer[BUFSIZ];
sprintf(kirkbuffer, "[%d]", np->index);
printf("%-6.6s %5.1f %7.2f %11.2f",
kirkbuffer ,
100 * ( np -> propself + np -> propchild ) / printtime ,
np -> propself / hz ,
np -> propchild / hz );
if((np->ncall + np->selfcalls) != 0){
printf(" %7ld", np->ncall);
if(np->selfcalls != 0)
printf("+%-7ld", np->selfcalls);
else
printf(" %7.7s ", "");
}
else{
printf(" %7.7s %7.7s ", "", "");
}
printname(np);
printf("\n");
}
void
printgprof(
nltype **timesortnlp)
{
unsigned long index;
nltype *parentp;
gprofheader();
for(index = 0; index < nname + ncycle; index ++){
parentp = timesortnlp[index];
if(zflag == FALSE &&
parentp->ncall == 0 &&
parentp->selfcalls == 0 &&
parentp->propself == 0 &&
parentp->propchild == 0 ){
continue;
}
if(!parentp->printflag){
continue;
}
if(parentp->name == 0 && parentp->cycleno != 0){
printcycle(parentp);
printmembers(parentp);
}
else{
printparents(parentp);
gprofline(parentp);
printchildren(parentp);
}
printf("\n");
printf("-----------------------------------------------\n");
printf("\n");
}
free(timesortnlp);
}
int
totalcmp(
nltype **npp1,
nltype **npp2)
{
nltype *np1, *np2;
double diff;
np1 = *npp1;
np2 = *npp2;
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));
}
static
void
printparents(
nltype *childp)
{
nltype *parentp;
arctype *arcp;
nltype *cycleheadp;
if(childp->cyclehead != 0){
cycleheadp = childp->cyclehead;
}
else{
cycleheadp = childp;
}
if(childp->parents == 0){
printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n",
"" , "" , "" , "" , "" , "" );
return;
}
sortparents(childp);
for(arcp = childp->parents; arcp; arcp = arcp->arc_parentlist){
parentp = arcp->arc_parentp;
if(childp == parentp ||
(childp->cycleno != 0 && parentp->cycleno == childp->cycleno)){
printf("%6.6s %5.5s %7.7s %11.11s %7ld %7.7s ",
"" , "" , "" , "", arcp->arc_count, "");
printname(parentp);
printf("\n");
}
else{
printf("%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld ",
"" , "" ,
arcp->arc_time / hz, arcp->arc_childtime / hz,
arcp->arc_count, cycleheadp->ncall);
printname(parentp);
printf("\n");
}
}
}
static
void
printchildren(
nltype *parentp)
{
nltype *childp;
arctype *arcp;
sortchildren(parentp);
arcp = parentp->children;
for(arcp = parentp->children; arcp; arcp = arcp->arc_childlist){
childp = arcp->arc_childp;
if(childp == parentp ||
(childp->cycleno != 0 && childp->cycleno == parentp->cycleno)){
printf("%6.6s %5.5s %7.7s %11.11s %7ld %7.7s ",
"", "", "", "", arcp->arc_count, "");
printname(childp);
printf("\n");
}
else{
printf("%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld ",
"", "",
arcp->arc_time / hz, arcp->arc_childtime / hz,
arcp->arc_count, childp->cyclehead->ncall);
printname(childp);
printf("\n");
}
}
}
void
printname(
nltype *selfp)
{
if(selfp->name != NULL){
printf("%s", selfp->name);
#ifdef DEBUG
if(debug & DFNDEBUG){
printf("{%d} ", selfp->toporder);
}
if(debug & PROPDEBUG){
printf("%5.2f%% ", selfp->propfraction);
}
#endif
}
if(selfp->cycleno != 0){
printf(" <cycle %d>", selfp->cycleno);
}
if(selfp->index != 0){
if(selfp->printflag){
printf(" [%d]", selfp->index );
}else{
printf(" (%d)", selfp->index );
}
}
}
static
void
sortchildren(
nltype *parentp)
{
arctype *arcp;
arctype *detachedp;
arctype sorted;
arctype *prevp;
detachedp = NULL;
sorted.arc_childlist = 0;
#ifdef notdef
for((arcp = parentp->children) && (detachedp = arcp->arc_childlist);
arcp;
(arcp = detachedp) && (detachedp = detachedp->arc_childlist)){
#endif
if((arcp = parentp->children) != NULL)
detachedp = arcp->arc_childlist;
while(arcp != NULL){
for(prevp = &sorted;
prevp->arc_childlist;
prevp = prevp->arc_childlist){
if(arccmp(arcp, prevp->arc_childlist) != LESSTHAN){
break;
}
}
arcp->arc_childlist = prevp->arc_childlist;
prevp->arc_childlist = arcp;
if((arcp = detachedp) != NULL)
detachedp = detachedp->arc_childlist;
}
parentp->children = sorted.arc_childlist;
}
static
void
sortparents(
nltype *childp)
{
arctype *arcp;
arctype *detachedp;
arctype sorted;
arctype *prevp;
detachedp = NULL;
sorted.arc_parentlist = 0;
#ifdef notdef
for((arcp = childp->parents) && (detachedp = arcp->arc_parentlist);
arcp;
(arcp = detachedp) && (detachedp = detachedp->arc_parentlist)){
#endif
if((arcp = childp->parents) != NULL)
detachedp = arcp->arc_parentlist;
while(arcp != NULL){
for(prevp = &sorted;
prevp->arc_parentlist;
prevp = prevp->arc_parentlist){
if(arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN){
break;
}
}
arcp->arc_parentlist = prevp->arc_parentlist;
prevp->arc_parentlist = arcp;
if((arcp = detachedp) != NULL)
detachedp = detachedp->arc_parentlist;
}
childp->parents = sorted.arc_parentlist;
}
static
void
printcycle(
nltype *cyclep)
{
char kirkbuffer[BUFSIZ];
sprintf(kirkbuffer, "[%d]", cyclep->index);
printf("%-6.6s %5.1f %7.2f %11.2f %7ld",
kirkbuffer,
100 * (cyclep->propself + cyclep->propchild) / printtime,
cyclep->propself / hz,
cyclep->propchild / hz,
cyclep->ncall);
if(cyclep->selfcalls != 0){
printf("+%-7ld", cyclep->selfcalls);
}
else{
printf(" %7.7s", "");
}
printf(" <cycle %d as a whole>\t[%d]\n",
cyclep->cycleno, cyclep->index);
}
static
void
printmembers(
nltype *cyclep)
{
nltype *memberp;
sortmembers(cyclep);
for(memberp = cyclep->cnext; memberp; memberp = memberp->cnext){
printf("%6.6s %5.5s %7.2f %11.2f %7ld",
"", "", memberp->propself / hz, memberp->propchild / hz,
memberp->ncall);
if(memberp->selfcalls != 0){
printf("+%-7ld", memberp->selfcalls);
}
else{
printf(" %7.7s", "");
}
printf(" ");
printname(memberp);
printf("\n");
}
}
static
void
sortmembers(
nltype *cyclep)
{
nltype *todo;
nltype *doing;
nltype *prev;
todo = cyclep->cnext;
cyclep->cnext = 0;
#ifdef notdef
for((doing = todo) && (todo = doing->cnext);
doing;
(doing = todo) && (todo = doing->cnext)){
#endif
if((doing = todo) != NULL)
todo = doing->cnext;
while(doing != NULL){
for(prev = cyclep; prev->cnext; prev = prev->cnext){
if(membercmp(doing, prev->cnext) == GREATERTHAN){
break;
}
}
doing->cnext = prev->cnext;
prev->cnext = doing;
if((doing = todo) != NULL)
todo = doing->cnext;
}
}
static
int
membercmp(
nltype *this,
nltype *that)
{
double thistime, thattime;
long thiscalls, thatcalls;
thistime = this->propself + this->propchild;
thattime = that->propself + that->propchild;
thiscalls = this->ncall + this->selfcalls;
thatcalls = that->ncall + that->selfcalls;
if(thistime > thattime){
return(GREATERTHAN);
}
if(thistime < thattime){
return(LESSTHAN);
}
if(thiscalls > thatcalls){
return(GREATERTHAN);
}
if(thiscalls < thatcalls){
return(LESSTHAN);
}
return(EQUALTO);
}
static
int
arccmp(
arctype *thisp,
arctype *thatp)
{
nltype *thisparentp, *thischildp, *thatparentp, *thatchildp;
double thistime, thattime;
thisparentp = thisp->arc_parentp;
thischildp = thisp->arc_childp;
thatparentp = thatp->arc_parentp;
thatchildp = thatp->arc_childp;
#ifdef DEBUG
if(debug & TIMEDEBUG){
printf("[arccmp] ");
printname(thisparentp);
printf(" calls ");
printname(thischildp);
printf(" %f + %f %ld/%ld\n",
thisp->arc_time, thisp->arc_childtime,
thisp->arc_count, thischildp->ncall);
printf("[arccmp] ");
printname(thatparentp);
printf(" calls ");
printname(thatchildp);
printf(" %f + %f %ld/%ld\n",
thatp->arc_time, thatp->arc_childtime,
thatp->arc_count, thatchildp->ncall);
printf("\n");
}
#endif
if(thisparentp == thischildp){
return(LESSTHAN);
}
if(thatparentp == thatchildp){
return(GREATERTHAN);
}
if(thisparentp->cycleno != 0 && thischildp->cycleno != 0 &&
thisparentp->cycleno == thischildp->cycleno){
if(thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
thatparentp->cycleno == thatchildp->cycleno){
if(thisp->arc_count < thatp->arc_count){
return(LESSTHAN);
}
if(thisp->arc_count > thatp->arc_count){
return(GREATERTHAN);
}
return(EQUALTO);
}
else{
return(LESSTHAN);
}
}
else{
if(thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
thatparentp->cycleno == thatchildp->cycleno){
return(GREATERTHAN);
}
else{
thistime = thisp->arc_time + thisp->arc_childtime;
thattime = thatp->arc_time + thatp->arc_childtime;
if(thistime < thattime)
return(LESSTHAN);
if(thistime > thattime)
return(GREATERTHAN);
if(thisp->arc_count < thatp->arc_count)
return(LESSTHAN);
if(thisp->arc_count > thatp->arc_count)
return(GREATERTHAN);
return(EQUALTO);
}
}
}
static
void
printblurb(
char *blurbname)
{
FILE *blurbfile;
int input;
blurbfile = fopen(blurbname, "r");
if(blurbfile == NULL){
perror(blurbname);
return;
}
while((input = getc(blurbfile)) != EOF){
putchar(input);
}
fclose(blurbfile);
}
static
int
namecmp(
nltype **npp1,
nltype **npp2)
{
return(strcmp((*npp1)->name, (*npp2)->name));
}
void
printindex(
void)
{
nltype **namesortnlp;
nltype *nlp;
unsigned long index, nnames, todo, i, j;
char peterbuffer[BUFSIZ];
namesortnlp = (nltype **)calloc(nname + ncycle, sizeof(nltype *));
if(namesortnlp == NULL)
fatal("ran out of memory for sorting");
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 *),
(int (*)(const void *, const void *))namecmp);
for(index = 1, todo = nnames; index <= (unsigned long)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, "<cycle %d>", nlp->cycleno);
printf("%-19.19s", peterbuffer);
}
}
printf("\n");
}
free(namesortnlp);
}