#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include <interp.h>#include "io.h"#include "../port/error.h"#include <isa.h>#include "kernel.h" /* Builtin module support */#include "bench.h"#include "benchmod.h" typedef enum { None, Calibrate, Base, Op, Intr, Dis, Gc, MS2T, xTest};static struct { int inuse; /* reference count */ int test; void* scratch; char* buf; int bufsz; char* wpos; void (*op)(void); vlong tickstart;} bench; static voidlog(char *msg, ...){ va_list ap; va_start(ap, msg); bench.wpos = vseprint(bench.wpos, bench.buf+bench.bufsz, msg, ap); va_end(ap);} voidelog(char *msg, ...){ va_list ap; if(bench.buf == 0) return; va_start(ap, msg); bench.wpos = vseprint(bench.wpos, bench.buf+bench.bufsz, msg, ap); va_end(ap);} static voidclear(void){ bench.wpos = bench.buf;} static longrep(void *to, long n, ulong offset){ long left = bench.wpos - bench.buf - offset; if(left < 0) left = 0; if(n > left) n = left; memmove(to, bench.buf+offset, n); return n;} static longnotest(int report, void *va, long n, ulong offset){ USED(report, va, n, offset); if(report) return rep(va, n, offset); return 0;} // Calibrationstatic long MS2TS = 0; // time stamps per millisecstatic long US2TS = 0; // time stamps per microsecond static longcal(int report, void *va, long n, ulong offset){ int tot, i, lim, low, max, pl, mdelay; ulong t; if(report) return rep(va, n, offset); clear(); setpri(PriRealtime); lim = 1000; low = 64000000; max = 0; tot = 0; mdelay = 1000; for(i=0; i<lim; i++){ do{ pl = splhi(); t = archrdtsc32(); microdelay(mdelay); t = archrdtsc32() - t; splx(pl); } while(t < 0); if(t < low) low = t; if(t > max) max = t; tot += t; } MS2TS = tot/lim; US2TS = MS2TS/1000; if(va) log("mdelay=%lud lim=%lud tot=%lud low=%lud max=%lud\n", mdelay, lim, tot, low, max); setpri(PriNormal); return n;} /* * ticks to format string *//*static*/ char *ts2str(vlong ticks){#define Nbuf 5 static char b[Nbuf][40]; static int n=Nbuf-1; char *fmt, *unit; double d; if(0){ print("ticks=%lld MS2TS=%ld\n", ticks, MS2TS); d = (double)ticks; print("1:%f\n", d); d = (double)ticks*1000; //print("2:%f\n", d); d = ((double)ticks)/MS2TS; //print("3:%f\n", d); } n = (n+1)%Nbuf; if(ticks > MS2TS*1000) { fmt = "%.2f %s"; unit = "s"; d = ((double)ticks/MS2TS) * 1000.0; } else if(ticks > MS2TS) { fmt = "%.2f %s"; unit = "ms"; d = (double)ticks/MS2TS; } else if(ticks > MS2TS/1000) { fmt = "%.2f %s"; unit = "us"; d = ((double)ticks*1000)/MS2TS; } else { fmt = "%.2f %s"; unit = "ns"; d = ((double)ticks*1000*1000)/MS2TS; } sprint(b[n], fmt, d, unit); return b[n];} /* * ticks to microseconds */static doublets2us(vlong ticks){ return ((double)ticks*1000)/MS2TS;} /* * microseconds timestamp */static vlongbus(int reset){ vlong now; if(US2TS == 0) return 0; if(reset) { bench.tickstart = archrdtsc(); return 0; } now = archrdtsc(); return ((now-bench.tickstart))/US2TS;} // Basestatic longbase(int report, void *va, long n, ulong offset){ int tot, i, lim, low, max, pl; ulong t; char *bm; if(report) return rep(va, n, offset); clear(); setpri(PriRealtime); lim = 1000; low = 64000000; max = 0; tot = 0; for(i=0; i<lim; i++){ do { pl = splhi(); t = archrdtsc32(); // do nothing t = archrdtsc32() - t; splx(pl); } while(t < 0); if(t < low) low = t; if(t > max) max = t; tot += t; } bm = ts2str(tot/lim); log("%d %lud %lud %lud %lud (%s)\n", up->pid, lim, tot, low, max, bm); setpri(PriNormal); return n;} // Timeop typedef struct Psync Psync; enum { Maxprocs=3,}; struct Psync { Rendez r; int flag; int id; int awaken;};static Psync timesync[Maxprocs];static Ref nactive;static Ref nbusy;static RWlock sync; static voidnilop(void){} static inttimev(void *a){ return *(int*)a;} static voidtimeop0(void *ap){ int tot, i, lim, low, max; ulong t; Psync *ps; char *bm; ps = ap; setpri(PriRealtime); incref(&nactive); sleep(&ps->r, timev, &ps->flag); rlock(&sync); lim = 1000; low = 64000000; max = 0; tot = 0; for(i=0; i<lim; i++){ do{ t = archrdtsc32(); (*bench.op)(); t = archrdtsc32() - t; }while(t < 0); if(t < low) low = t; if(t > max) max = t; tot += t; } bm = ts2str(tot/lim); log("%d %lud %lud %lud %lud (%s)\n", up->pid, lim, tot, low, max, bm); runlock(&sync); pexit("", 0);} static longtimeop(int report, void *va, long n, ulong offset){ int i, np, pl; if(report) return rep(va, n, offset); clear(); bench.op = 0; if(strncmp(va, "nil", 3) == 0) bench.op = nilop; else if(strncmp(va, "sched", 5) == 0) bench.op = sched; else return 0; for(np=1; np<=Maxprocs; np++) { nactive.ref = 0; wlock(&sync); log("%d procs\n", np); setpri(PriRealtime); for(i=0; i<np; i++) { timesync[i].id = i; kproc("timeop", timeop0, ×ync[i], 0); } while(nactive.ref < np) tsleep(&up->sleep, return0, 0, 20); for(i=0; i<np; i++){ timesync[i].flag = 1; wakeup(×ync[i].r); } sched(); pl = splhi(); setpri(PriNormal); wunlock(&sync); // now they run wlock(&sync); // wait for last reader wunlock(&sync); splx(pl); } return n;} typedef struct Ictr Ictr;struct Ictr { ulong base; ulong sleep; ulong spllo; ulong intr; ulong isave; ulong arrive; ulong wakeup; ulong awake;};static Ictr counters[5/*100*/], *curct;static int intrwant;static Rendez vous;int spltbl; /* set by spllo */int intrtbl; /* set by intrvec() */int isavetbl; /* set by intrvec() */ static int ienable; static voidintrwake(void){ if(ienable == 0) return; ienable = 0; if(spltbl == 0) // not used here curct->spllo = curct->intr = curct->isave = archrdtsc32(); else { curct->spllo = spltbl; curct->intr = intrtbl; curct->isave = isavetbl; } curct->arrive = archrdtsc32(); intrwant = 0; wakeup(&vous); curct->wakeup = archrdtsc32();} /* * sleep calls intrtest with splhi (under lock): * provoke the interrupt now, so that it is guaranteed * not to happen until sleep has queued the process, * forcing wakeup to do something. */static intintrtest(void*){ ienable = 1; /* enable recording on interrupt */ curct->sleep = archrdtsc32(); return intrwant==0;} static longintrtime(int report, void *va, long n, ulong offset){ Ictr *ic; long t; int i; char *bm; if(report) return rep(va, n, offset); clear(); setpri(PriRealtime); sched(); curct = counters; ienable = 0; addclock0link(intrwake, MS2HZ); for(i=0; i<nelem(counters); i++){ curct = &counters[i]; intrwant = 1; curct->base = archrdtsc32(); sleep(&vous, intrtest, nil); curct->awake = archrdtsc32(); sched(); /* just to slow it down between trials */ } log("interrupt\n"); for(i=0; i<nelem(counters); i++){ ic = &counters[i]; t = ic->awake - ic->base; bm = ts2str(ic->awake - ic->arrive); ic->awake -= ic->wakeup; ic->wakeup -= ic->arrive; ic->arrive -= ic->isave; ic->isave -= ic->intr; ic->intr -= ic->spllo; ic->spllo -= ic->sleep; ic->sleep -= ic->base; log("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld (%s)\n", ic->sleep, ic->spllo, ic->intr, ic->isave, ic->arrive, ic->wakeup, ic->awake, t, bm); } setpri(PriNormal); return n;} /* DIS operation timing */ typedef struct { vlong n; /* count */ vlong min; vlong max; vlong sum; vlong sumsq; /* sum of squares */} Stat; static voidstat(enum { Reset, Inc } op, Stat *c, vlong val){ switch(op) { case Reset: c->n = 0; c->sum = 0; c->sumsq = 0; c->min = 0; c->max = 0; break; case Inc: c->n++; c->sum += val; c->sumsq += val*val; break; } if(val < c->min || c->n == 1) c->min = val; if(val > c->max || c->n == 1) c->max = val;} static voidstatinc(Stat *d, Stat *s){ d->n += s->n; d->sum += s->sum; d->sumsq += s->sumsq; if(s->min < d->min || d->n == s->n) d->min = s->min; if(s->max > d->max || d->n == s->n) d->max = s->max;} enum{ HSIZE = 31, MAXCOUNT = 100000000L,}; typedef struct { int op; int pc; long count; Stat t; /* combined dec and execution time */} Istat; typedef struct Mstat Mstat;struct Mstat { char* name; char* path; int ninst; Istat* inst; Inst* base; Mstat* hash; Mstat* link;}; struct{ Mstat* hash[HSIZE]; Mstat* list;} vmstat; Lines 1–500 of 1165. Load more
#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include <interp.h> #include "io.h" #include "../port/error.h" #include <isa.h> #include "kernel.h" /* Builtin module support */ #include "bench.h" #include "benchmod.h" typedef enum { None, Calibrate, Base, Op, Intr, Dis, Gc, MS2T, xTest}; static struct { int inuse; /* reference count */ int test; void* scratch; char* buf; int bufsz; char* wpos; void (*op)(void); vlong tickstart; } bench; static void log(char *msg, ...) { va_list ap; va_start(ap, msg); bench.wpos = vseprint(bench.wpos, bench.buf+bench.bufsz, msg, ap); va_end(ap); } void elog(char *msg, ...) { va_list ap; if(bench.buf == 0) return; va_start(ap, msg); bench.wpos = vseprint(bench.wpos, bench.buf+bench.bufsz, msg, ap); va_end(ap); } static void clear(void) { bench.wpos = bench.buf; } static long rep(void *to, long n, ulong offset) { long left = bench.wpos - bench.buf - offset; if(left < 0) left = 0; if(n > left) n = left; memmove(to, bench.buf+offset, n); return n; } static long notest(int report, void *va, long n, ulong offset) { USED(report, va, n, offset); if(report) return rep(va, n, offset); return 0; } // Calibration static long MS2TS = 0; // time stamps per millisec static long US2TS = 0; // time stamps per microsecond static long cal(int report, void *va, long n, ulong offset) { int tot, i, lim, low, max, pl, mdelay; ulong t; if(report) return rep(va, n, offset); clear(); setpri(PriRealtime); lim = 1000; low = 64000000; max = 0; tot = 0; mdelay = 1000; for(i=0; i<lim; i++){ do{ pl = splhi(); t = archrdtsc32(); microdelay(mdelay); t = archrdtsc32() - t; splx(pl); } while(t < 0); if(t < low) low = t; if(t > max) max = t; tot += t; } MS2TS = tot/lim; US2TS = MS2TS/1000; if(va) log("mdelay=%lud lim=%lud tot=%lud low=%lud max=%lud\n", mdelay, lim, tot, low, max); setpri(PriNormal); return n; } /* * ticks to format string */ /*static*/ char * ts2str(vlong ticks) { #define Nbuf 5 static char b[Nbuf][40]; static int n=Nbuf-1; char *fmt, *unit; double d; if(0){ print("ticks=%lld MS2TS=%ld\n", ticks, MS2TS); d = (double)ticks; print("1:%f\n", d); d = (double)ticks*1000; //print("2:%f\n", d); d = ((double)ticks)/MS2TS; //print("3:%f\n", d); } n = (n+1)%Nbuf; if(ticks > MS2TS*1000) { fmt = "%.2f %s"; unit = "s"; d = ((double)ticks/MS2TS) * 1000.0; } else if(ticks > MS2TS) { fmt = "%.2f %s"; unit = "ms"; d = (double)ticks/MS2TS; } else if(ticks > MS2TS/1000) { fmt = "%.2f %s"; unit = "us"; d = ((double)ticks*1000)/MS2TS; } else { fmt = "%.2f %s"; unit = "ns"; d = ((double)ticks*1000*1000)/MS2TS; } sprint(b[n], fmt, d, unit); return b[n]; } /* * ticks to microseconds */ static double ts2us(vlong ticks) { return ((double)ticks*1000)/MS2TS; } /* * microseconds timestamp */ static vlong bus(int reset) { vlong now; if(US2TS == 0) return 0; if(reset) { bench.tickstart = archrdtsc(); return 0; } now = archrdtsc(); return ((now-bench.tickstart))/US2TS; } // Base static long base(int report, void *va, long n, ulong offset) { int tot, i, lim, low, max, pl; ulong t; char *bm; if(report) return rep(va, n, offset); clear(); setpri(PriRealtime); lim = 1000; low = 64000000; max = 0; tot = 0; for(i=0; i<lim; i++){ do { pl = splhi(); t = archrdtsc32(); // do nothing t = archrdtsc32() - t; splx(pl); } while(t < 0); if(t < low) low = t; if(t > max) max = t; tot += t; } bm = ts2str(tot/lim); log("%d %lud %lud %lud %lud (%s)\n", up->pid, lim, tot, low, max, bm); setpri(PriNormal); return n; } // Timeop typedef struct Psync Psync; enum { Maxprocs=3, }; struct Psync { Rendez r; int flag; int id; int awaken; }; static Psync timesync[Maxprocs]; static Ref nactive; static Ref nbusy; static RWlock sync; static void nilop(void) { } static int timev(void *a) { return *(int*)a; } static void timeop0(void *ap) { int tot, i, lim, low, max; ulong t; Psync *ps; char *bm; ps = ap; setpri(PriRealtime); incref(&nactive); sleep(&ps->r, timev, &ps->flag); rlock(&sync); lim = 1000; low = 64000000; max = 0; tot = 0; for(i=0; i<lim; i++){ do{ t = archrdtsc32(); (*bench.op)(); t = archrdtsc32() - t; }while(t < 0); if(t < low) low = t; if(t > max) max = t; tot += t; } bm = ts2str(tot/lim); log("%d %lud %lud %lud %lud (%s)\n", up->pid, lim, tot, low, max, bm); runlock(&sync); pexit("", 0); } static long timeop(int report, void *va, long n, ulong offset) { int i, np, pl; if(report) return rep(va, n, offset); clear(); bench.op = 0; if(strncmp(va, "nil", 3) == 0) bench.op = nilop; else if(strncmp(va, "sched", 5) == 0) bench.op = sched; else return 0; for(np=1; np<=Maxprocs; np++) { nactive.ref = 0; wlock(&sync); log("%d procs\n", np); setpri(PriRealtime); for(i=0; i<np; i++) { timesync[i].id = i; kproc("timeop", timeop0, ×ync[i], 0); } while(nactive.ref < np) tsleep(&up->sleep, return0, 0, 20); for(i=0; i<np; i++){ timesync[i].flag = 1; wakeup(×ync[i].r); } sched(); pl = splhi(); setpri(PriNormal); wunlock(&sync); // now they run wlock(&sync); // wait for last reader wunlock(&sync); splx(pl); } return n; } typedef struct Ictr Ictr; struct Ictr { ulong base; ulong sleep; ulong spllo; ulong intr; ulong isave; ulong arrive; ulong wakeup; ulong awake; }; static Ictr counters[5/*100*/], *curct; static int intrwant; static Rendez vous; int spltbl; /* set by spllo */ int intrtbl; /* set by intrvec() */ int isavetbl; /* set by intrvec() */ static int ienable; static void intrwake(void) { if(ienable == 0) return; ienable = 0; if(spltbl == 0) // not used here curct->spllo = curct->intr = curct->isave = archrdtsc32(); else { curct->spllo = spltbl; curct->intr = intrtbl; curct->isave = isavetbl; } curct->arrive = archrdtsc32(); intrwant = 0; wakeup(&vous); curct->wakeup = archrdtsc32(); } /* * sleep calls intrtest with splhi (under lock): * provoke the interrupt now, so that it is guaranteed * not to happen until sleep has queued the process, * forcing wakeup to do something. */ static int intrtest(void*) { ienable = 1; /* enable recording on interrupt */ curct->sleep = archrdtsc32(); return intrwant==0; } static long intrtime(int report, void *va, long n, ulong offset) { Ictr *ic; long t; int i; char *bm; if(report) return rep(va, n, offset); clear(); setpri(PriRealtime); sched(); curct = counters; ienable = 0; addclock0link(intrwake, MS2HZ); for(i=0; i<nelem(counters); i++){ curct = &counters[i]; intrwant = 1; curct->base = archrdtsc32(); sleep(&vous, intrtest, nil); curct->awake = archrdtsc32(); sched(); /* just to slow it down between trials */ } log("interrupt\n"); for(i=0; i<nelem(counters); i++){ ic = &counters[i]; t = ic->awake - ic->base; bm = ts2str(ic->awake - ic->arrive); ic->awake -= ic->wakeup; ic->wakeup -= ic->arrive; ic->arrive -= ic->isave; ic->isave -= ic->intr; ic->intr -= ic->spllo; ic->spllo -= ic->sleep; ic->sleep -= ic->base; log("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld (%s)\n", ic->sleep, ic->spllo, ic->intr, ic->isave, ic->arrive, ic->wakeup, ic->awake, t, bm); } setpri(PriNormal); return n; } /* DIS operation timing */ typedef struct { vlong n; /* count */ vlong min; vlong max; vlong sum; vlong sumsq; /* sum of squares */ } Stat; static void stat(enum { Reset, Inc } op, Stat *c, vlong val) { switch(op) { case Reset: c->n = 0; c->sum = 0; c->sumsq = 0; c->min = 0; c->max = 0; break; case Inc: c->n++; c->sum += val; c->sumsq += val*val; break; } if(val < c->min || c->n == 1) c->min = val; if(val > c->max || c->n == 1) c->max = val; } static void statinc(Stat *d, Stat *s) { d->n += s->n; d->sum += s->sum; d->sumsq += s->sumsq; if(s->min < d->min || d->n == s->n) d->min = s->min; if(s->max > d->max || d->n == s->n) d->max = s->max; } enum { HSIZE = 31, MAXCOUNT = 100000000L, }; typedef struct { int op; int pc; long count; Stat t; /* combined dec and execution time */ } Istat; typedef struct Mstat Mstat; struct Mstat { char* name; char* path; int ninst; Istat* inst; Inst* base; Mstat* hash; Mstat* link; }; struct { Mstat* hash[HSIZE]; Mstat* list; } vmstat;