Commit | Line | Data |
---|---|---|
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 | ||
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 | UNIT *lowpc; | |
22 | UNIT *highpc; | |
23 | int ncount; | |
24 | }; | |
25 | ||
26 | struct nl nl[1200]; | |
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 | unsigned pcl; | |
39 | unsigned pch; | |
40 | unsigned bufs; | |
41 | int nname; | |
42 | double ftime; | |
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(); | |
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 | ||
245 | print: | |
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 | ||
264 | min(a, b) | |
265 | unsigned a, b; | |
266 | { | |
267 | if (a<b) | |
268 | return(a); | |
269 | return(b); | |
270 | } | |
271 | ||
272 | max(a, b) | |
273 | unsigned a, b; | |
274 | { | |
275 | if (a>b) | |
276 | return(a); | |
277 | return(b); | |
278 | } | |
279 | ||
280 | valcmp(p1, p2) | |
281 | struct nl *p1, *p2; | |
282 | { | |
283 | return(p1->value - p2->value); | |
284 | } | |
285 | ||
286 | timcmp(p1, p2) | |
287 | struct 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 | ||
299 | done() | |
300 | { | |
301 | ||
302 | #ifdef plot | |
303 | if(vflg) { | |
304 | point(0, -2040); | |
305 | closepl(); | |
306 | } | |
307 | #endif | |
308 | exit(0); | |
309 | } |