Charles.Forsyth20060303a828770d19 years agoHistory
1230 lines · 23.9 KB · Brainfuck
RawDownload
implement Profile; include "sys.m";	sys: Sys;include "draw.m";include "bufio.m";	bufio: Bufio;	Iobuf: import bufio;include "workdir.m";	workdir: Workdir;include "debug.m";	debug: Debug;	Sym: import debug;include "dis.m";	dism: Dis;include "profile.m"; # merge common code PROF: con "/prof";CTL: con "ctl";NAME: con "name";MPATH: con "path";HISTOGRAM: con "histogram"; inited: int;modl: string;lasterr: string; bspath := array[] of{	("/dis/",		"/appl/cmd/"),	("/dis/",		"/appl/"),}; error(s: string){	lasterr = sys->sprint("%s: %r", s);} error0(s: string){	lasterr = s;} cleare(){	lasterr = nil;} lasterror(): string{	return lasterr;} init(): int{	cleare();	sys = load Sys Sys->PATH;	bufio = load Bufio Bufio->PATH;	debug = load Debug Debug->PATH;	if(debug == nil){		error("cannot load Debug module");		return -1;	}	debug->init();	(ok, nil) := sys->stat(PROF + "/ctl");	if (ok == -1) {		if(sys->bind("#P", PROF, Sys->MREPL|Sys->MCREATE) < 0){			error(sys->sprint("cannot bind prof device to /prof"));			return -1;		}	}	inited = 1;	return 0;} end(): int{	cleare();	inited = 0;	modl = nil;	if(write(mkpath(PROF, CTL), "end") < 0)		return -1;	return 0;} start(): int{	cleare();	if(!inited && init() < 0)		return -1;	if(write(mkpath(PROF, CTL), "module " + modl) < 0)		return -1;	if(write(mkpath(PROF, CTL), "start") < 0)		return -1;	return 0;} cpstart(pid: int): int{	cleare();	if(!inited && init() < 0)		return -1;	if(write(mkpath(PROF, CTL), "module " + modl) < 0)		return -1;	if(write(mkpath(PROF, CTL), "startcp " + string pid) < 0)		return -1;	return 0;} memstart(m: int): int{	cleare();	if(!inited && init() < 0)		return -1;	if(modl != nil && write(mkpath(PROF, CTL), "module " + modl) < 0)		return -1;	start := "startmp";	if(m == 0)		m = MAIN|HEAP|IMAGE;	if(m&MAIN)		start += "1";	if(m&HEAP)		start += "2";	if(m&IMAGE)		start += "3";	if(write(mkpath(PROF, CTL), start) < 0)		return -1;	return 0;} stop(): int{	cleare();	if(!inited && init() < 0)		return -1;	if(write(mkpath(PROF, CTL), "stop") < 0)		return -1;	return 0;} sample(i: int): int{	cleare();	if(i <= 0){		error0(sys->sprint("bad sample rate %d", i));		return -1;	}	if(write(mkpath(PROF, CTL), "interval " + string i) < 0)		return -1;	return 0;} profile(m: string): int{	cleare();	modl = m + " " + modl;	return 0;} stats(): Prof{	mp: Modprof;	p: Prof;	mpl: list of Modprof; 	cleare();	fd := sys->open(PROF, Sys->OREAD);	if(fd == nil){		error(sys->sprint("cannot open %s for reading", PROF));		return (nil, 0, nil);	}	total := 0;	for(;;){		(nr, d) := sys->dirread(fd);		if(nr <= 0)			break;		for(i := 0; i < nr; i++){			if(d[i].name == CTL)				continue;			dn := mkpath(PROF, d[i].name);			mp.name = read(mkpath(dn, NAME));			mp.path = read(mkpath(dn, MPATH));			fdh := sys->open(mkpath(dn, HISTOGRAM), Sys->OREAD);			if(fdh == nil)				continue;			(mp.srcpath, mp.linetab, mp.funtab, mp.total) = tprofile(fdh, mp.path);			if((sp := getb(mp.path)) != nil)				mp.srcpath = sp;			if(mp.total != 0){				mpl = mp :: mpl;				total += mp.total;			}		}	}	p.mods = mpl;	p.total = total;	return p;} cpstats(rec: int, v: int): Prof{	m: string;	mp: Modprof;	p: Prof;	mpl: list of Modprof; 	cleare();	fd := sys->open(PROF, Sys->OREAD);	if(fd == nil){		error(sys->sprint("cannot open %s for reading", PROF));		return (nil, 0, nil);	}	total := 0;	for(;;){		(nr, d) := sys->dirread(fd);		if(nr <= 0)			break;		for(i:=0; i<nr; i++){			if(d[i].name == CTL)				continue;			dn := mkpath(PROF, d[i].name);			mp.name = read(mkpath(dn, NAME));			mp.path = read(mkpath(dn, MPATH));			fdh := sys->open(mkpath(dn, HISTOGRAM), Sys->OREAD);			if(fdh == nil)				continue;			(m, mp.srcpath, mp.rawtab, mp.linetab, mp.rngtab, mp.total, mp.coverage) = cprofile(fdh, mp.path, rec, v);			if(mp.name == nil)				mp.name = m;			if((sp := getb(mp.path)) != nil)				mp.srcpath = sp;			if(len mp.rawtab > 0){				mpl = mp :: mpl;				total += mp.total;			}		}	}	p.mods = mpl;	p.total = total;	return p;} cpfstats(v: int): Prof{	mp: Modprof;	p: Prof;	mpl: list of Modprof; 	cleare();	total := 0;	(nil, l) := sys->tokenize(modl, " ");	for( ; l != nil; l = tl l){		s := hd l;		suf := suff(s);		if(suf == nil)			s += ".dis";		else			s = repsuff(s, "."+suf, ".dis");		if(!exists(s) && s[0] != '/' && s[0:2] != "./")			s = "/dis/"+s;		mp.path = s;		(mp.name, mp.srcpath, mp.rawtab, mp.linetab, mp.rngtab, mp.total, mp.coverage) = cprofile(nil, mp.path, 1, v);		if((sp := getb(mp.path)) != nil)			mp.srcpath = sp;		if(len mp.rawtab > 0){			mpl = mp :: mpl;			total += mp.total;		}	}	p.mods = mpl;	p.total = total;	return p;} memstats(): Prof{	mp: Modprof;	p: Prof;	mpl: list of Modprof; 	cleare();	fd := sys->open(PROF, Sys->OREAD);	if(fd == nil){		error(sys->sprint("cannot open %s for reading", PROF));		return (nil, 0, nil);	}	total := totale := 0;	for(;;){		(nr, d) := sys->dirread(fd);		if(nr <= 0)			break;		for(i:=0; i<nr; i++){			if(d[i].name == CTL)				continue;			dn := mkpath(PROF, d[i].name);			mp.name = read(mkpath(dn, NAME));			mp.path = read(mkpath(dn, MPATH));			fdh := sys->open(mkpath(dn, HISTOGRAM), Sys->OREAD);			if(fdh == nil)				continue;			mp.totals = array[1] of int;			(mp.srcpath, mp.linetab, mp.funtab, mp.total, mp.totals[0]) = mprofile(fdh, mp.path);			if((sp := getb(mp.path)) != nil)				mp.srcpath = sp;			if(mp.total != 0 || mp.totals[0] != 0){				mpl = mp :: mpl;				total += mp.total;				totale += mp.totals[0];			}		}	}	p.mods = mpl;	p.total = total;	p.totals = array[1] of int;	p.totals[0] = totale;	return p;} tprofile(fd: ref Sys->FD, dis: string): (string, array of int, array of Funprof, int){	sbl := findsbl(dis);	if(sbl == nil){		error0(sys->sprint("cannot locate symbol table file for %s", dis));		return (nil, nil, nil, 0);	}	(sym, err) := debug->sym(sbl);	if(sym == nil){		error0(sys->sprint("bad symbol table file: %s", err));		return (nil, nil, nil, 0);	}	nlines := 0;	nl := len sym.src;	for(i := 0; i < nl; i++){		if((l := sym.src[i].stop.line) > nlines)			nlines = l;	}	name := sym.src[0].start.file;	line := array[nlines+1] of int;	for(i = 0; i <= nlines; i++)		line[i] = 0;	nf := len sym.fns;	fun := array[nf] of Funprof;	for(i = 0; i < nf; i++){		fun[i].name = sym.fns[i].name;		# src seems to be always nil		# fun[i].file = sym.fns[i].src.start.file;		# fun[i].line = (sym.fns[i].src.start.line+sym.fns[i].src.stop.line)/2;		src := sym.pctosrc(sym.fns[i].offset);		if(src != nil)			fun[i].line = src.start.line;		else			fun[i].line = 0;		fun[i].count = 0;	}	buf := array[32] of byte;	# pc := 0;	tot := 0;	fi := 0;# for(i=0; i < nl; i++) sys->print("%d -> %d\n", i, sym.pctosrc(i).start.line);	while((m := sys->read(fd, buf, len buf)) > 0){		(nw, lw) := sys->tokenize(string buf[0:m], " ");		if(nw != 2){			error0("bad histogram data");			return  (nil, nil, nil, 0);		}		pc := int hd lw;		f := int hd tl lw;		rpc := pc-1;		src := sym.pctosrc(rpc);		if(src == nil)			continue;		l1 := src.start.line;		l2 := src.stop.line;		if(l1 == 0 || l2 == 0)			continue;		if((nl = l2-l1+1) == 1)			line[l1] += f;		else{			q := f/nl;			r := f-q*nl;			for(i = l1; i <= l2; i++)				line[i] += q+(r-->0);		}		if(fi < nf){			if(rpc >= sym.fns[fi].offset && rpc < sym.fns[fi].stoppc)				fun[fi].count += f;			else{				while(fi < nf && rpc >= sym.fns[fi].stoppc)					fi++;				# fi++;				if(fi >= nf && f != 0)					error0(sys->sprint("bad fn index"));				if(fi < nf)					fun[fi].count += f;			}		}		tot += f;# sys->print("pc %d count %d l1 %d l2 %d\n", rpc, f, l1, l2);	}	return (name, line, fun, tot);} cprofile(fd: ref Sys->FD, dis: string, rec: int, v: int): (string, string, array of (int, int), array of int, array of ref Range, int, int){	freq := v&FREQUENCY;	sbl := findsbl(dis);	if(sbl == nil){		error0(sys->sprint("cannot locate symbol table file for %s", dis));		return (nil, nil, nil, nil, nil, 0, 0);	}	(sym, err) := debug->sym(sbl);	if(sym == nil){		error0(sys->sprint("bad symbol table file: %s", err));		return (nil, nil, nil, nil, nil, 0, 0);	}	nlines := 0;	nl := len sym.src;	for(i := 0; i < nl; i++){		if((l := sym.src[i].start.line) > nlines)			nlines = l;		if((l = sym.src[i].stop.line) > nlines)			nlines = l;	}	name := sym.src[0].start.file;	line := array[nlines+1] of int;	for(i = 0; i <= nlines; i++){		if(freq)			line[i] = -1;		else			line[i] = 0;	}	rng := array[nlines+1] of ref Range;	for(i = 0; i < nl; i++)		cover(i, -1, sym, line, rng, freq);	buf := array[32] of byte;	nr := 0;	r := array[1024] of (int, int);	while((m := sys->read(fd, buf, len buf)) > 0){		(nw, lw) := sys->tokenize(string buf[0:m], " ");		if(nw != 2){			error0("bad histogram data");			return  (nil, nil, nil, nil, nil, 0, 0);		}		(r, nr) = add(r, nr, int hd lw, int hd tl lw);	}	r = clip(r, nr);	if(rec){		wt := nr > 0;		prf := repsuff(sbl, ".sbl", ".prf");		if(exists(prf)){			if(stamp(sbl) > stamp(prf)){				error0(sys->sprint("%s later than %s", sbl, prf));				return (nil, nil, nil, nil, nil, 0, 0);			}			r = mergeprof(r, readprof(prf));			nr = len r;		}		if(wt && writeprof(prf, r) < 0){			error0(sys->sprint("cannot write profile file %s", prf));			return (nil, nil, nil, nil, nil, 0, 0);		}	}	tot := 0;	lpc := 0;	dise := dist := 0;	for(i = 0; i < nr; i++){		(pc, f) := r[i];		for( ; lpc < pc; lpc++){			cover(lpc, 0, sym, line, rng, freq);			dist++;		}		cover(pc, f, sym, line, rng, freq);		dist++;		if(f != 0)			dise++;		tot += f;		lpc = pc+1;	}	for( ; lpc < nl; lpc++){		cover(lpc, 0, sym, line, rng, freq);		dist++;	}	if(dist == 0)		dist = 1;	return (sym.name, name, r, line, rng, tot, (100*dise)/dist);} show(p: Prof, v: int): int{	i: int; 	cleare();	tot := p.total;	if(tot == 0)		return 0;	verbose := v&VERBOSE;	fullhdr := v&FULLHDR;	for(ml := p.mods; ml != nil; ml = tl ml){

Lines 1–500 of 1230.