Commit | Line | Data |
---|---|---|
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 | ||
10 | typedef short UNIT; /* unit of profiling */ | |
11 | ||
12 | struct stat stbuf; | |
13 | struct nl { | |
14 | char name[8]; | |
15 | unsigned value; | |
16 | float time; | |
17 | long ncall; | |
18 | }; | |
19 | ||
20 | struct hdr { | |
21 | short *lowpc; | |
22 | short *highpc; | |
23 | int ncount; | |
24 | }; | |
25 | ||
26 | struct nl nl[600]; | |
27 | ||
28 | struct cnt { | |
29 | unsigned cvalue; | |
30 | long cncall; | |
31 | } cbuf[350]; | |
32 | ||
33 | FILE *pfile, *nfile; | |
34 | unsigned highpc; | |
35 | unsigned lowpc; | |
36 | double ransca; | |
37 | double ranoff; | |
38 | int pcl; | |
39 | int pch; | |
40 | unsigned bufs; | |
41 | int nname; | |
42 | double time; | |
43 | double actime; | |
44 | double totime; | |
45 | double maxtime; | |
46 | double scale; | |
47 | double lastx; | |
48 | double lasty; | |
49 | struct nl *np; | |
50 | struct nl *npe; | |
51 | int aflg; | |
52 | int vflg; | |
53 | int lflg; | |
54 | long symoff; | |
55 | ||
56 | main(argc, argv) | |
57 | char **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 | ||
253 | print: | |
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 | ||
272 | min(a, b) | |
273 | { | |
274 | if (a<b) | |
275 | return(a); | |
276 | return(b); | |
277 | } | |
278 | ||
279 | max(a, b) | |
280 | { | |
281 | if (a>b) | |
282 | return(a); | |
283 | return(b); | |
284 | } | |
285 | ||
286 | valcmp(p1, p2) | |
287 | struct nl *p1, *p2; | |
288 | { | |
289 | return(p1->value - p2->value); | |
290 | } | |
291 | ||
292 | timcmp(p1, p2) | |
293 | struct 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 | ||
305 | cntcmp(p1, p2) | |
306 | struct cnt *p1, *p2; | |
307 | { | |
308 | return(p1->cvalue - p2->cvalue); | |
309 | } | |
310 | ||
311 | done() | |
312 | { | |
313 | ||
314 | #ifdef plot | |
315 | if(vflg) { | |
316 | point(0, -2040); | |
317 | closepl(); | |
318 | } | |
319 | #endif | |
320 | exit(0); | |
321 | } |