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. Load more
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){