Research V7 development
[unix-history] / usr / src / cmd / prof.c
CommitLineData
34b9dafd
KT
1/*
2 * Print execution profile
3 */
4
5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <a.out.h>
9
10typedef short UNIT; /* unit of profiling */
11
12struct stat stbuf;
13struct nl {
14 char name[8];
15 unsigned value;
16 float time;
17 long ncall;
18};
19
20struct hdr {
21 UNIT *lowpc;
22 UNIT *highpc;
23 int ncount;
24};
25
26struct nl nl[1200];
27
28struct cnt {
29 unsigned cvalue;
30 long cncall;
31} cbuf[350];
32
33FILE *pfile, *nfile;
34unsigned highpc;
35unsigned lowpc;
36double ransca;
37double ranoff;
38unsigned pcl;
39unsigned pch;
40unsigned bufs;
41int nname;
42double ftime;
43double actime;
44double totime;
45double maxtime;
46double scale;
47double lastx;
48double lasty;
49struct nl *np;
50struct nl *npe;
51int aflg;
52int vflg;
53int lflg;
54long symoff;
55
56main(argc, argv)
57char **argv;
58{
59 char *namfil;
60 int timcmp(), valcmp();
61 int i, overlap;
62 long pfpos;
63 double lastsx;
64 struct cnt *cp;
65 double tx, ty;
66 struct exec xbuf;
67 struct hdr h;
68
69 lowpc = -1;
70 highpc = -1;
71 argv++;
72 namfil = "a.out";
73 while (argc>1) {
74 if (**argv == '-') {
75 if (*++*argv == 'l')
76 lflg++;
77 if (**argv == 'a')
78 aflg = 040;
79 if(**argv == 'v')
80 vflg++;
81 if(**argv >= '0' && **argv <= '9') {
82 i = atoi(*argv);
83 if(lowpc == -1)
84 lowpc = i;
85 else
86 highpc = i;
87 }
88 } else
89 namfil = *argv;
90 argc--;
91 argv++;
92 }
93 if (lowpc >= 100)
94 lowpc = 0;
95 if(highpc <= lowpc || highpc > 100)
96 highpc = 100;
97 ransca = 100./(highpc-lowpc);
98 ranoff = 2040. + 40.8*lowpc*ransca;
99 if((nfile=fopen(namfil,"r"))==NULL) {
100 fprintf(stderr, "%s: not found\n", namfil);
101 done();
102 }
103 fread((char *)&xbuf, 1, sizeof(xbuf), nfile);
104 if (xbuf.a_magic!=A_MAGIC1 && xbuf.a_magic!=A_MAGIC2 && xbuf.a_magic!=A_MAGIC3) {
105 fprintf(stderr, "%s: bad format\n", namfil);
106 done();
107 }
108 symoff = (long)xbuf.a_text + xbuf.a_data;
109 if ((xbuf.a_flag&01) == 0)
110 symoff *= 2;
111 fseek(nfile, symoff+sizeof(xbuf), 0);
112 if((pfile = fopen("mon.out","r")) == NULL) {
113 fprintf(stderr, "No mon.out\n");
114 done();
115 }
116 fstat(fileno(pfile), &stbuf);
117 fread((char *)&h, sizeof(struct hdr), 1, pfile);
118 lowpc = h.lowpc - (UNIT *)0;
119 highpc = h.highpc - (UNIT *)0;
120 bufs = stbuf.st_size - sizeof(struct hdr) - h.ncount*sizeof(struct cnt);
121 fread((char *)cbuf, sizeof(struct cnt), h.ncount, pfile);
122 pfpos = ftell(pfile);
123 npe = nl;
124 for (nname = 0; xbuf.a_syms > 0; xbuf.a_syms -= sizeof(struct nlist)) {
125 struct nlist nbuf;
126 fread((char *)&nbuf, sizeof(nbuf), 1, nfile);
127 if (nbuf.n_type!=N_TEXT && nbuf.n_type!=N_TEXT+N_EXT)
128 continue;
129 if (aflg==0 && nbuf.n_type!=N_TEXT+N_EXT)
130 continue;
131 npe->value = nbuf.n_value/sizeof(UNIT);
132 for (i=0; i<8; i++)
133 npe->name[i] = nbuf.n_name[i];
134 npe++;
135 nname++;
136 }
137 if (nname == 0) {
138 fprintf(stderr, "%s: no symbols\n", namfil);
139 done();
140 }
141 npe->value = -1;
142 npe++;
143 for (cp = cbuf; cp < &cbuf[h.ncount]; cp++)
144 for (np = nl; np < npe; np++)
145 if ((unsigned)(cp->cvalue/sizeof(UNIT) - np->value) <=10) {
146 np->ncall = cp->cncall;
147 break;
148 }
149 qsort(nl, nname, sizeof(struct nl), valcmp);
150 scale = highpc - lowpc;
151 scale /= bufs/sizeof(UNIT);
152 for(i=0;;i++) {
153 register j;
154 unsigned UNIT ccnt;
155 fread((char *)&ccnt, sizeof(ccnt), 1, pfile);
156 if(feof(pfile))
157 break;
158 if (ccnt == 0)
159 continue;
160 pcl = lowpc + scale*i;
161 pch = lowpc + scale*(i+1);
162 ftime = ccnt;
163 totime += ftime;
164 if(ftime > maxtime)
165 maxtime = ftime;
166 for (j=0; j<nname; j++) {
167 if (pch < nl[j].value)
168 break;
169 if (pcl >= nl[j+1].value)
170 continue;
171 overlap=(min(pch,nl[j+1].value)-max(pcl,nl[j].value));
172 nl[j].time += overlap*ftime/scale;
173 }
174 }
175 if (totime==0.0) {
176 fprintf(stderr, "No time accumulated\n");
177 done();
178 }
179#ifdef plot
180 if(!vflg)
181 goto print;
182 openpl();
183 erase();
184 space(-2048, -2048, 2048, 2048);
185 line(-2040, -2040, -2040, 2040);
186 line(0, 2040, 0, -2040);
187 for(i=0; i<11; i++)
188 line(-2040, 2040-i*408, 0, 2040-i*408);
189 lastx = 0.;
190 lasty = ranoff;
191 scale = (4080.*ransca)/(bufs/sizeof(UNIT));
192 fclose(pfile); /*to turn off eof*/
193 pfile = fopen("mon.out", "r");
194 fseek(pfile, pfpos, 0);
195 lastsx = 0.0;
196 for(;;) {
197 unsigned UNIT ccnt;
198 fread((char *)&ccnt, sizeof(ccnt), 1, pfile);
199 if(feof(pfile))
200 break;
201 ftime = ccnt;
202 tx = lastsx;
203 ty = lasty;
204 lastsx -= 2000.*ftime/totime;
205 lasty -= scale;
206 if(lasty >= -2040. && ty <= 2040.) {
207 line((int)tx, (int)ty, (int)lastsx, (int)lasty);
208 if (ccnt!=0 || lastx!=0.0) {
209 tx = lastx;
210 lastx = -ftime*2000./maxtime;
211 ty += scale/2;
212 line(0, (int)ty, (int)tx, (int)ty);
213 }
214 }
215 }
216 scale = (4080.*ransca)/(highpc-lowpc);
217 lastx = 50.;
218 for(np = nl; np<npe; np++) {
219 if(np->value < lowpc)
220 continue;
221 if(np->value >= highpc)
222 continue;
223 ftime = np->time/totime;
224 lasty = ranoff - (np->value - lowpc)*scale;
225 if(lasty >= -2040. && lasty <= 2040.) {
226 char bufl[8+3], *namp;
227 register j;
228 line(0, (int)lasty, 50, (int)lasty);
229 line((int)(lastx-50),(int)lasty,(int)lastx,(int)lasty);
230 point((int)(lastx+30), (int)(lasty+10));
231 namp = bufl;
232 for(j=0; j<8; j++)
233 if(np->name[j] != '_')
234 *namp++ = np->name[j];
235 *namp++ = '\n';
236 *namp++ = 0;
237 label(bufl);
238 }
239 lastx += 500.;
240 if(lastx > 2000.)
241 lastx = 50.;
242 }
243 done();
244
245print:
246#endif
247 actime = 0;
248 printf(" name %%time cumsecs #call ms/call\n");
249 if (!lflg)
250 qsort(nl, nname, sizeof(struct nl), timcmp);
251 for (np = nl; np<npe-1; np++) {
252 ftime = np->time/totime;
253 actime += np->time;
254 printf("%8.8s%6.1f%9.2f", np->name, 100*ftime, actime/60);
255 if(np->ncall!=0) {
256 printf("%6ld", np->ncall);
257 printf(" %7.2f\n", np->time/(np->ncall*.06));
258 } else
259 printf("\n");
260 }
261 done();
262}
263
264min(a, b)
265unsigned a, b;
266{
267 if (a<b)
268 return(a);
269 return(b);
270}
271
272max(a, b)
273unsigned a, b;
274{
275 if (a>b)
276 return(a);
277 return(b);
278}
279
280valcmp(p1, p2)
281struct nl *p1, *p2;
282{
283 return(p1->value - p2->value);
284}
285
286timcmp(p1, p2)
287struct nl *p1, *p2;
288{
289 float d;
290
291 d = p2->time - p1->time;
292 if (d > 0.0)
293 return(1);
294 if (d < 0.0)
295 return(-1);
296 return(0);
297}
298
299done()
300{
301
302#ifdef plot
303 if(vflg) {
304 point(0, -2040);
305 closepl();
306 }
307#endif
308 exit(0);
309}