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