]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/prof.c
snoopy(8): avoid extra spaces in dhcp filter output
[plan9front.git] / sys / src / cmd / prof.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5
6 typedef struct Data     Data;
7 typedef struct Pc       Pc;
8 typedef struct Acc      Acc;
9
10 struct Data
11 {
12         ushort  down;
13         ushort  right;
14         ulong   pc;
15         ulong   count;
16         ulong   time;
17 };
18
19 struct Pc
20 {
21         Pc      *next;
22         ulong   pc;
23 };
24
25 struct Acc
26 {
27         char    *name;
28         ulong   pc;
29         ulong   ms;
30         ulong   calls;
31 };
32
33 Data*   data;
34 Acc*    acc;
35 ulong   ms;
36 long    nsym;
37 long    ndata;
38 int     dflag;
39 int     rflag;
40 Biobuf  bout;
41 int     tabstop = 4;
42 int     verbose;
43
44 void    syms(char*);
45 void    datas(char*);
46 void    graph(int, ulong, Pc*);
47 void    plot(void);
48 char*   name(ulong);
49 void    indent(int);
50 char*   defaout(void);
51
52 void
53 main(int argc, char *argv[])
54 {
55         char *s;
56
57         s = getenv("tabstop");
58         if(s!=nil && strtol(s,0,0)>0)
59                 tabstop = strtol(s,0,0);
60         ARGBEGIN{
61         case 'v':
62                 verbose = 1;
63                 break;
64         case 'd':
65                 dflag = 1;
66                 break;
67         case 'r':
68                 rflag = 1;
69                 break;
70         default:
71                 fprint(2, "usage: prof [-dr] [8.out] [prof.out]\n");
72                 exits("usage");
73         }ARGEND
74         Binit(&bout, 1, OWRITE);
75         if(argc > 0)
76                 syms(argv[0]);
77         else
78                 syms(defaout());
79         if(argc > 1)
80                 datas(argv[1]);
81         else
82                 datas("prof.out");
83         if(ndata){
84                 if(dflag)
85                         graph(0, data[0].down, 0);
86                 else
87                         plot();
88         }
89         exits(0);
90 }
91
92 void
93 swapdata(Data *dp)
94 {
95         dp->down = beswab(dp->down);
96         dp->right = beswab(dp->right);
97         dp->pc = beswal(dp->pc);
98         dp->count = beswal(dp->count);
99         dp->time = beswal(dp->time);
100 }
101
102 int
103 acmp(void *va, void *vb)
104 {
105         Acc *a, *b;
106         ulong ua, ub;
107
108         a = va;
109         b = vb;
110         ua = a->ms;
111         ub = b->ms;
112
113         if(ua > ub)
114                 return 1;
115         if(ua < ub)
116                 return -1;
117         return 0;
118 }
119
120 void
121 syms(char *cout)
122 {
123         Fhdr f;
124         int fd;
125
126         if((fd = open(cout, 0)) < 0){
127                 perror(cout);
128                 exits("open");
129         }
130         if (!crackhdr(fd, &f)) {
131                 fprint(2, "can't read text file header\n");
132                 exits("read");
133         }
134         if (f.type == FNONE) {
135                 fprint(2, "text file not an a.out\n");
136                 exits("file type");
137         }
138         if (syminit(fd, &f) < 0) {
139                 fprint(2, "syminit: %r\n");
140                 exits("syms");
141         }
142         close(fd);
143 }
144
145 void
146 datas(char *dout)
147 {
148         int fd;
149         Dir *d;
150         int i;
151
152         if((fd = open(dout, 0)) < 0){
153                 perror(dout);
154                 exits("open");
155         }
156         d = dirfstat(fd);
157         if(d == nil){
158                 perror(dout);
159                 exits("stat");
160         }
161         ndata = d->length/sizeof(data[0]);
162         data = malloc(ndata*sizeof(Data));
163         if(data == 0){
164                 fprint(2, "prof: can't malloc data\n");
165                 exits("data malloc");
166         }
167         if(read(fd, data, d->length) != d->length){
168                 fprint(2, "prof: can't read data file\n");
169                 exits("data read");
170         }
171         free(d);
172         close(fd);
173         for (i = 0; i < ndata; i++)
174                 swapdata(data+i);
175 }
176
177 char*
178 name(ulong pc)
179 {
180         Symbol s;
181         static char buf[16];
182
183         if (findsym(pc, CTEXT, &s))
184                 return(s.name);
185         snprint(buf, sizeof(buf), "#%lux", pc);
186         return buf;
187 }
188
189 void
190 graph(int ind, ulong i, Pc *pc)
191 {
192         long time, count, prgm;
193         Pc lpc;
194
195         if(i >= ndata){
196                 fprint(2, "prof: index out of range %ld [max %ld]\n", i, ndata);
197                 return;
198         }
199         count = data[i].count;
200         time = data[i].time;
201         prgm = data[i].pc;
202         if(time < 0)
203                 time += data[0].time;
204         if(data[i].right != 0xFFFF)
205                 graph(ind, data[i].right, pc);
206         indent(ind);
207         if(count == 1)
208                 Bprint(&bout, "%s:%lud\n", name(prgm), time);
209         else
210                 Bprint(&bout, "%s:%lud/%lud\n", name(prgm), time, count);
211         if(data[i].down == 0xFFFF)
212                 return;
213         lpc.next = pc;
214         lpc.pc = prgm;
215         if(!rflag){
216                 while(pc){
217                         if(pc->pc == prgm){
218                                 indent(ind+1);
219                                 Bprint(&bout, "...\n");
220                                 return;
221                         }
222                         pc = pc->next;
223                 }
224         }
225         graph(ind+1, data[i].down, &lpc);
226 }
227 /*
228  *      assume acc is ordered by increasing text address.
229  */
230 long
231 symind(ulong pc)
232 {
233         int top, bot, mid;
234
235         bot = 0;
236         top = nsym;
237         for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
238                 if (pc < acc[mid].pc)
239                         top = mid;
240                 else
241                 if (mid != nsym-1 && pc >= acc[mid+1].pc)
242                         bot = mid;
243                 else
244                         return mid;
245         }
246         return -1;
247 }
248
249 ulong
250 sum(ulong i)
251 {
252         long j, dtime, time;
253         int k;
254         static indent;
255
256         if(i >= ndata){
257                 fprint(2, "prof: index out of range %ld [max %ld]\n", i, ndata);
258                 return 0;
259         }
260         j = symind(data[i].pc);
261         time = data[i].time;
262         if(time < 0)
263                 time += data[0].time;
264         if (verbose){
265                 for(k = 0; k < indent; k++)
266                         print(" ");
267                 print("%lud: %ld/%lud", i, data[i].time, data[i].count);
268                 if (j >= 0)
269                         print(" %s\n", acc[j].name);
270                 else
271                         print(" 0x%lux\n", data[i].pc);
272         }
273         dtime = 0;
274         if(data[i].down != 0xFFFF){
275                 indent++;
276                 dtime = sum(data[i].down);
277                 indent--;
278         }
279         j = symind(data[i].pc);
280         if (j >= 0) {
281                 acc[j].ms += time - dtime;
282                 ms += time - dtime;
283                 acc[j].calls += data[i].count;
284         }
285         if(data[i].right == 0xFFFF)
286                 return time;
287         return time + sum(data[i].right);
288 }
289
290 void
291 plot(void)
292 {
293         Symbol s;
294
295         for (nsym = 0; textsym(&s, nsym); nsym++) {
296                 acc = realloc(acc, (nsym+1)*sizeof(Acc));
297                 if(acc == 0){
298                         fprint(2, "prof: malloc fail\n");
299                         exits("acc malloc");
300                 }
301                 acc[nsym].name = s.name;
302                 acc[nsym].pc = s.value;
303                 acc[nsym].calls = acc[nsym].ms = 0;
304         }
305         sum(data[0].down);
306         qsort(acc, nsym, sizeof(Acc), acmp);
307         Bprint(&bout, "  %%     Time     Calls  Name\n");
308         if(ms == 0)
309                 ms = 1;
310         while (--nsym >= 0) {
311                 if(acc[nsym].calls)
312                         Bprint(&bout, "%4.1f %8.3f %8lud\t%s\n",
313                                 (100.0*acc[nsym].ms)/ms,
314                                 acc[nsym].ms/1000.0,
315                                 acc[nsym].calls,
316                                 acc[nsym].name);
317         }
318 }
319
320 void
321 indent(int ind)
322 {
323         int j;
324
325         j = 2*ind;
326         while(j >= tabstop){
327                 Bwrite(&bout, ".\t", 2);
328                 j -= tabstop;
329         }
330         if(j)
331                 Bwrite(&bout, ".                            ", j);
332 }
333
334 char*   trans[] =
335 {
336         "386",          "8.out",
337         "68020",                "2.out",
338         "amd64",        "6.out",
339         "arm",          "5.out",
340         "mips",         "v.out",
341         "power",                "q.out",
342         "sparc",                "k.out",
343         "spim",         "0.out",
344         0,0
345 };
346
347 char*
348 defaout(void)
349 {
350         char *p;
351         int i;
352
353         p = getenv("objtype");
354         if(p)
355         for(i=0; trans[i]; i+=2)
356                 if(strcmp(p, trans[i]) == 0)
357                         return trans[i+1];
358         return trans[1];
359 }