Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/cmd/prof.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
	"alpha",		"7.out",
339
	"amd64",	"6.out",
340
	"arm",		"5.out",
341
	"mips",		"v.out",
342
	"power",		"q.out",
343
	"sparc",		"k.out",
344
	"spim",		"0.out",
345
	0,0
346
};
347
 
348
char*
349
defaout(void)
350
{
351
	char *p;
352
	int i;
353
 
354
	p = getenv("objtype");
355
	if(p)
356
	for(i=0; trans[i]; i+=2)
357
		if(strcmp(p, trans[i]) == 0)
358
			return trans[i+1];
359
	return trans[1];
360
}