/* * Print execution profile */ #include #include #include #include typedef short UNIT; /* unit of profiling */ struct stat stbuf; struct nl { char name[8]; unsigned value; float time; long ncall; }; struct hdr { UNIT *lowpc; UNIT *highpc; int ncount; }; struct nl nl[1200]; struct cnt { unsigned cvalue; long cncall; } cbuf[350]; FILE *pfile, *nfile; unsigned highpc; unsigned lowpc; double ransca; double ranoff; unsigned pcl; unsigned pch; unsigned bufs; int nname; double ftime; double actime; double totime; double maxtime; double scale; double lastx; double lasty; struct nl *np; struct nl *npe; int aflg; int vflg; int lflg; long symoff; main(argc, argv) char **argv; { char *namfil; int timcmp(), valcmp(); int i, overlap; long pfpos; double lastsx; struct cnt *cp; double tx, ty; struct exec xbuf; struct hdr h; lowpc = -1; highpc = -1; argv++; namfil = "a.out"; while (argc>1) { if (**argv == '-') { if (*++*argv == 'l') lflg++; if (**argv == 'a') aflg = 040; if(**argv == 'v') vflg++; if(**argv >= '0' && **argv <= '9') { i = atoi(*argv); if(lowpc == -1) lowpc = i; else highpc = i; } } else namfil = *argv; argc--; argv++; } if (lowpc >= 100) lowpc = 0; if(highpc <= lowpc || highpc > 100) highpc = 100; ransca = 100./(highpc-lowpc); ranoff = 2040. + 40.8*lowpc*ransca; if((nfile=fopen(namfil,"r"))==NULL) { fprintf(stderr, "%s: not found\n", namfil); done(); } fread((char *)&xbuf, 1, sizeof(xbuf), nfile); if (xbuf.a_magic!=A_MAGIC1 && xbuf.a_magic!=A_MAGIC2 && xbuf.a_magic!=A_MAGIC3) { fprintf(stderr, "%s: bad format\n", namfil); done(); } symoff = (long)xbuf.a_text + xbuf.a_data; if ((xbuf.a_flag&01) == 0) symoff *= 2; fseek(nfile, symoff+sizeof(xbuf), 0); if((pfile = fopen("mon.out","r")) == NULL) { fprintf(stderr, "No mon.out\n"); done(); } fstat(fileno(pfile), &stbuf); fread((char *)&h, sizeof(struct hdr), 1, pfile); lowpc = h.lowpc - (UNIT *)0; highpc = h.highpc - (UNIT *)0; bufs = stbuf.st_size - sizeof(struct hdr) - h.ncount*sizeof(struct cnt); fread((char *)cbuf, sizeof(struct cnt), h.ncount, pfile); pfpos = ftell(pfile); npe = nl; for (nname = 0; xbuf.a_syms > 0; xbuf.a_syms -= sizeof(struct nlist)) { struct nlist nbuf; fread((char *)&nbuf, sizeof(nbuf), 1, nfile); if (nbuf.n_type!=N_TEXT && nbuf.n_type!=N_TEXT+N_EXT) continue; if (aflg==0 && nbuf.n_type!=N_TEXT+N_EXT) continue; npe->value = nbuf.n_value/sizeof(UNIT); for (i=0; i<8; i++) npe->name[i] = nbuf.n_name[i]; npe++; nname++; } if (nname == 0) { fprintf(stderr, "%s: no symbols\n", namfil); done(); } npe->value = -1; npe++; for (cp = cbuf; cp < &cbuf[h.ncount]; cp++) for (np = nl; np < npe; np++) if ((unsigned)(cp->cvalue/sizeof(UNIT) - np->value) <=10) { np->ncall = cp->cncall; break; } qsort(nl, nname, sizeof(struct nl), valcmp); scale = highpc - lowpc; scale /= bufs/sizeof(UNIT); for(i=0;;i++) { register j; unsigned UNIT ccnt; fread((char *)&ccnt, sizeof(ccnt), 1, pfile); if(feof(pfile)) break; if (ccnt == 0) continue; pcl = lowpc + scale*i; pch = lowpc + scale*(i+1); ftime = ccnt; totime += ftime; if(ftime > maxtime) maxtime = ftime; for (j=0; j= nl[j+1].value) continue; overlap=(min(pch,nl[j+1].value)-max(pcl,nl[j].value)); nl[j].time += overlap*ftime/scale; } } if (totime==0.0) { fprintf(stderr, "No time accumulated\n"); done(); } #ifdef plot if(!vflg) goto print; openpl(); erase(); space(-2048, -2048, 2048, 2048); line(-2040, -2040, -2040, 2040); line(0, 2040, 0, -2040); for(i=0; i<11; i++) line(-2040, 2040-i*408, 0, 2040-i*408); lastx = 0.; lasty = ranoff; scale = (4080.*ransca)/(bufs/sizeof(UNIT)); fclose(pfile); /*to turn off eof*/ pfile = fopen("mon.out", "r"); fseek(pfile, pfpos, 0); lastsx = 0.0; for(;;) { unsigned UNIT ccnt; fread((char *)&ccnt, sizeof(ccnt), 1, pfile); if(feof(pfile)) break; ftime = ccnt; tx = lastsx; ty = lasty; lastsx -= 2000.*ftime/totime; lasty -= scale; if(lasty >= -2040. && ty <= 2040.) { line((int)tx, (int)ty, (int)lastsx, (int)lasty); if (ccnt!=0 || lastx!=0.0) { tx = lastx; lastx = -ftime*2000./maxtime; ty += scale/2; line(0, (int)ty, (int)tx, (int)ty); } } } scale = (4080.*ransca)/(highpc-lowpc); lastx = 50.; for(np = nl; npvalue < lowpc) continue; if(np->value >= highpc) continue; ftime = np->time/totime; lasty = ranoff - (np->value - lowpc)*scale; if(lasty >= -2040. && lasty <= 2040.) { char bufl[8+3], *namp; register j; line(0, (int)lasty, 50, (int)lasty); line((int)(lastx-50),(int)lasty,(int)lastx,(int)lasty); point((int)(lastx+30), (int)(lasty+10)); namp = bufl; for(j=0; j<8; j++) if(np->name[j] != '_') *namp++ = np->name[j]; *namp++ = '\n'; *namp++ = 0; label(bufl); } lastx += 500.; if(lastx > 2000.) lastx = 50.; } done(); print: #endif actime = 0; printf(" name %%time cumsecs #call ms/call\n"); if (!lflg) qsort(nl, nname, sizeof(struct nl), timcmp); for (np = nl; nptime/totime; actime += np->time; printf("%8.8s%6.1f%9.2f", np->name, 100*ftime, actime/60); if(np->ncall!=0) { printf("%6ld", np->ncall); printf(" %7.2f\n", np->time/(np->ncall*.06)); } else printf("\n"); } done(); } min(a, b) unsigned a, b; { if (ab) return(a); return(b); } valcmp(p1, p2) struct nl *p1, *p2; { return(p1->value - p2->value); } timcmp(p1, p2) struct nl *p1, *p2; { float d; d = p2->time - p1->time; if (d > 0.0) return(1); if (d < 0.0) return(-1); return(0); } done() { #ifdef plot if(vflg) { point(0, -2040); closepl(); } #endif exit(0); }