ref: f242ed181ff7118392737a3493e840aed9de4be1
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Jun 3 11:20:23 EDT 2024
initial commit: a collection of oddball scripts
--- /dev/null
+++ b/basic.rc
@@ -1,0 +1,7 @@
+#!/bin/rc -e
+
+. common.rc
+
+setup
+echo hi > $fs/test
+assert ~ `{cat $fs/test} hi--- /dev/null
+++ b/build.rc
@@ -1,0 +1,21 @@
+#!/bin/rc -e
+
+. common.rc
+
+setup
+
+cd $fs
+
+# we don't want to clobber the installed
+# libs with something corrupt, so copy
+# them in and bind them over.
+mkdir -p $cputype/lib
+dircp /$cputype/lib $cputype/lib
+bind $cputype/lib /$cputype/lib
+
+# clone our repo
+git/clone /dist/plan9front
+bind plan9front/sys/include /sys/include
+
+cd plan9front/sys/src
+mk all
--- /dev/null
+++ b/common.rc
@@ -1,0 +1,28 @@
+#!/bin/rc
+
+rfork ne
+
+srv=gefstest.$pid
+fs=/n/$srv
+
+fn setup{+ if(! test -f test.fs){+ dd -if /dev/zero -of test.fs -bs 1kk -count 2k
+ chmod +t test.fs
+ }
+ ../6.out -r -f test.fs
+ ../6.out -m 32 -Au glenda -f test.fs -n $srv
+ mount -c /srv/$srv $fs
+}
+
+fn assert {+ st=$status
+ if(! ~ $#st 0){+ echo $st >[1=2]
+ exit $st
+ }
+}
+
+fn sigexit{+ unmount $fs
+}
--- /dev/null
+++ b/freplay.c
@@ -1,0 +1,202 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+File* ctlfile;
+File* datfile;
+char* mountpt = "/mnt/replay";
+char* srvname = "replay";
+char* logfile;
+char* replayfile;
+char* membuf;
+vlong membufsz;
+vlong replaycount = -1;
+int logfd = -1;
+int replayfd = -1;
+vlong nwrites;
+
+void
+log1(int fd, void *buf, vlong off, vlong sz)
+{+ char *p, hdr[12];
+
+ p = hdr;
+ PBIT64(p, off); p += 8;
+ PBIT32(p, sz);
+ if(write(fd, hdr, sizeof(hdr)) == -1)
+ sysfatal("write header: %r");+ if(write(fd, buf, sz) == -1)
+ sysfatal("write data: %r\n");+}
+
+int
+replay1(int fd)
+{+ uchar *p, hdr[12];
+ vlong o;
+ int n, r;
+
+ r = readn(fd, hdr, 12);
+ if(r == 0)
+ return 0;
+ if(r != 12)
+ sysfatal("failed to read operation header: %r");+
+ p = hdr;
+ o = GBIT64(p); p += 8;
+ n = GBIT32(p);
+ if(o + n > membufsz)
+ sysfatal("operation exceeds buffer size");+ if(readn(fd, membuf + o, n) != n)
+ sysfatal("read op: %r");+ nwrites++;
+ return 1;
+}
+
+void
+readmembuf(Req *r, void *s, vlong n)
+{+ r->ofcall.count = r->ifcall.count;
+ if(r->ifcall.offset >= n){+ r->ofcall.count = 0;
+ return;
+ }
+ if(r->ifcall.offset+r->ofcall.count > n)
+ r->ofcall.count = n - r->ifcall.offset;
+ memmove(r->ofcall.data, (char*)s+r->ifcall.offset, r->ofcall.count);
+}
+
+void
+fsread(Req *r)
+{+ char buf[128];
+
+ if(r->fid->file == datfile){+ readmembuf(r, membuf, membufsz);
+ respond(r, nil);
+ }else if(r->fid->file == ctlfile){+ snprint(buf, sizeof(buf), "writes %lld\n", nwrites);
+ readstr(r, buf);
+ respond(r, nil);
+ }else
+ abort();
+}
+
+void
+fswrite(Req *r)
+{+ if(r->fid->file == datfile){+ if(logfile == nil){+ respond(r, "read-only replay file: no log defined");
+ return;
+ }
+ if(r->ifcall.offset + r->ifcall.count > membufsz){+ respond(r, "operation exceeds file size");
+ return;
+ }
+ log1(logfd, r->ifcall.data, r->ifcall.offset, r->ifcall.count);
+ memcpy(membuf + r->ifcall.offset, r->ifcall.data, r->ifcall.count);
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ nwrites++;
+ }else if(r->fid->file == ctlfile){+ if(strncmp(r->ifcall.data, "exit", 4) == 0){+ print("exiting...\n");+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ exits(nil);
+ }else if(strncmp(r->ifcall.data, "step", 4) == 0){+ r->ofcall.count = r->ifcall.count;
+ if(replayfd == -1)
+ respond(r, "no active replay");
+ else if(!replay1(replayfd))
+ respond(r, "no replay left");
+ else
+ respond(r, nil);
+ }else
+ respond(r, "unknown ctl message");
+ }else
+ abort();
+}
+
+void
+usage(void)
+{+ fprint(2, "usage: %s [-l log] [-r replay] [-c count] file\n", argv0);
+ exits("usage");+}
+
+static Srv fs = {+ .read = fsread,
+ .write = fswrite,
+};
+void
+main(int argc, char *argv[])
+{+ int fd;
+ vlong n, off;
+ char *uid;
+ Dir *d;
+ int i;
+
+ ARGBEGIN{+ case 'd':
+ chatty9p++;
+ break;
+ case 'l':
+ logfile = EARGF(usage());
+ break;
+ case 'r':
+ replayfile = EARGF(usage());
+ break;
+ case 'c':
+ replaycount = atoi(EARGF(usage()));
+ break;
+ case 'm':
+ mountpt = EARGF(usage());
+ break;
+ case 's':
+ srvname = EARGF(usage());
+ break;
+ default:
+ usage();
+ }ARGEND;
+
+ if(argc != 1)
+ usage();
+
+ if((fd = open(argv[0], OREAD)) == -1)
+ sysfatal("open %s: %r", argv[0]);+ if((d = dirfstat(fd)) == nil)
+ sysfatal("failed to stat file: %r");+ if((membuf = sbrk(d->length)) == nil)
+ sysfatal("failed to allocate buffer: %r");+ memset(membuf, 0, d->length);
+ for(off = 0; off < d->length; off += n)
+ if((n = read(fd, membuf+off, IOUNIT)) <= 0)
+ sysfatal("read %s@%lld: short read: %r", argv[0], off);+ membufsz = d->length;
+ free(d);
+ if(replayfile != nil){+ if((replayfd = open(replayfile, OREAD)) == -1)
+ sysfatal("failed to open replay file: %r");+ for(i = 0; i < replaycount || replaycount == -1; i++)
+ if(replay1(replayfd) == 0)
+ break;
+ print("replayed %d ops\n", i);+ }
+
+ if(logfile != nil){+ if((logfd = create(logfile, OWRITE, 0666)) == -1)
+ sysfatal("failed to open log file: %r");+ }
+ uid = getuser();
+ fs.tree = alloctree(uid, uid, DMDIR|0555, nil);
+ ctlfile = createfile(fs.tree->root, "ctl", uid, 0666, nil);
+ datfile = createfile(fs.tree->root, "data", uid, 0666, nil);
+ datfile->length = membufsz;
+ postmountsrv(&fs, srvname, mountpt, MREPL);
+ exits(nil);
+}
--- /dev/null
+++ b/fsbench.c
@@ -1,0 +1,518 @@
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+#include <thread.h>
+
+int mainstacksize = 2*1024*1024;
+typedef struct Bench Bench;
+enum {+ KiB = 1024ULL,
+ MiB = 1024ULL*KiB,
+ GiB = 1024ULL*MiB,
+ Bufsz = IOUNIT,
+};
+
+enum {+ Bps,
+ Fps,
+};
+
+struct Bench {+ char *name;
+ char *unit;
+ vlong (*fn)(Bench*);
+ vlong reps;
+ int nproc;
+ int id;
+ Channel *rc;
+
+ vlong i0;
+ vlong i1;
+ vlong i2;
+ char *s0;
+ char *s1;
+};
+
+#define GBIT64(p) ((u32int)(((uchar*)(p))[0]|(((uchar*)(p))[1]<<8)|\
+ (((uchar*)(p))[2]<<16)|(((uchar*)(p))[3]<<24)) |\
+ ((uvlong)(((uchar*)(p))[4]|(((uchar*)(p))[5]<<8)|\
+ (((uchar*)(p))[6]<<16)|(((uchar*)(p))[7]<<24)) << 32))
+vlong
+vrand(vlong n)
+{+ uchar buf[8];
+ vlong slop, v;
+
+ slop = 0x7fffffffffffffffULL % n;
+ do{+ prng(buf, 8);
+ v = GBIT64(buf);
+ }while(v <= slop);
+ return v % n;
+}
+
+vlong
+wrfile_la(Bench *b)
+{+ char buf[Bufsz];
+ vlong i;
+ int fd;
+
+ if((fd = create(b->s0, OWRITE, 0666)) == -1)
+ sysfatal("open: %r");+ for(i = 0; i < b->i0; i += Bufsz)
+ if(write(fd, buf, Bufsz) != Bufsz)
+ sysfatal("write: %r");+ close(fd);
+ return b->i0/MiB;
+}
+
+vlong
+wrfile_ra(Bench *b)
+{+ char buf[Bufsz];
+ vlong i, n, j, t, *off;
+ int fd;
+
+ n = b->i0/Bufsz;
+ if((fd = create(b->s0, OWRITE, 0666)) == -1)
+ sysfatal("open: %r");+ if((off = malloc(n*sizeof(vlong))) == nil)
+ sysfatal("malloc: %r");+ for(i = 0; i < n; i++)
+ off[i] = i*Bufsz;
+ for (i = n - 1; i > 0; i--) {+ j = vrand(i+1);
+ t = off[i];
+ off[i] = off[j];
+ off[j] = t;
+ }
+ for(i = 0; i < n; i++)
+ if(pwrite(fd, buf, Bufsz, off[i]) != Bufsz)
+ sysfatal("write: %r");+ close(fd);
+ free(off);
+ return b->i0/MiB;
+}
+
+vlong
+wrfile_rr(Bench *b)
+{+ char buf[Bufsz];
+ vlong i, n, j, t, *off;
+ int fd;
+
+ n = b->i0/Bufsz;
+ if((fd = create(b->s0, OWRITE, 0666)) == -1)
+ sysfatal("open: %r");+ if((off = malloc(n*sizeof(vlong))) == nil)
+ sysfatal("malloc: %r");+ for(i = 0; i < n; i++)
+ off[i] = i*Bufsz;
+ for (i = n - 1; i > 0; i--) {+ j = vrand(i+1);
+ t = off[i];
+ off[i] = off[j];
+ off[j] = t;
+ }
+ for(i = 0; i < n; i++)
+ if(pwrite(fd, buf, Bufsz, off[i] + vrand(100)) != Bufsz)
+ sysfatal("write: %r");+ close(fd);
+ free(off);
+ return b->i0/MiB;
+}
+
+vlong
+rdfile_la(Bench *b)
+{+ char path[128], buf[Bufsz];
+ vlong i, rep;
+ int fd;
+
+ if(b->id == -1)
+ snprint(path, sizeof(path), "%s", b->s0);
+ else if(b->i1 != 0)
+ snprint(path, sizeof(path), "%s.%lld", b->s0, b->id % b->i1);
+ else
+ snprint(path, sizeof(path), "%s.%d", b->s0, b->id);
+ if((fd = open(path, OREAD)) == -1)
+ sysfatal("open: %r");+ for(rep = 0; rep < b->reps; rep++){+ seek(fd, 0, 0);
+ for(i = 0; i < b->i0; i += Bufsz)
+ if(read(fd, buf, Bufsz) != Bufsz)
+ sysfatal("write: %r");+ }
+ close(fd);
+ return b->reps*(b->i0/MiB);
+}
+vlong
+rdfile_ra(Bench *b)
+{+ char path[128], buf[Bufsz];
+ vlong i, rep;
+ uvlong off;
+ int fd;
+
+ if(b->id == -1)
+ snprint(path, sizeof(path), "%s", b->s0);
+ else if(b->i1 != 0)
+ snprint(path, sizeof(path), "%s.%lld", b->s0, b->id % b->i1);
+ else
+ snprint(path, sizeof(path), "%s.%d", b->s0, b->id);
+ if((fd = open(path, OREAD)) == -1)
+ sysfatal("open: %r");+ for(rep = 0; rep < b->reps; rep++){+ seek(fd, 0, 0);
+ for(i = 0; i < b->i0; i += Bufsz){+ off = vrand(b->i0-Bufsz) & ~((vlong)Bufsz-1);
+ if(pread(fd, buf, Bufsz, off) != Bufsz)
+ sysfatal("write: %r");+ }
+ }
+ close(fd);
+ return b->reps*(b->i0/MiB);
+}
+
+vlong
+rwfile_lala(Bench *b)
+{+ char buf[64];
+ Bench bb;
+
+ bb = *b;
+ if(b->id >= b->i1)
+ return rdfile_la(&bb);
+ else{+ snprint(buf, sizeof(buf), "%s%d.w%d", b->s0, getpid(), b->id);
+ bb.s0 = buf;
+ return wrfile_la(&bb);
+ }
+}
+
+vlong
+rdfile_rr(Bench *b)
+{+ char path[128], buf[Bufsz];
+ vlong i, rep;
+ uvlong off;
+ int fd;
+
+ if(b->id == -1)
+ snprint(path, sizeof(path), "%s", b->s0);
+ else if(b->i1 != 0)
+ snprint(path, sizeof(path), "%s.%lld", b->s0, b->id % b->i1);
+ else
+ snprint(path, sizeof(path), "%s.%d", b->s0, b->id);
+ if((fd = open(path, OREAD)) == -1)
+ sysfatal("open: %r");+ for(rep = 0; rep < b->reps; rep++){+ for(i = 0; i < b->i0; i += Bufsz){+ off = vrand(b->i0-Bufsz);
+ if(pread(fd, buf, Bufsz, off) != Bufsz)
+ sysfatal("read: %r");+ }
+ }
+ close(fd);
+ return b->reps*(b->i0/MiB);
+}
+
+vlong
+createflat(Bench *b)
+{+ char buf[Bufsz];
+ int i, fd;
+
+ for(i = 0; i < b->i0; i++){+ snprint(buf, sizeof(buf), "%s%d", b->s0, i);
+ if((fd = create(buf, OWRITE, 0666)) == -1)
+ sysfatal("create: %r");+ if(b->i1 != 0)
+ write(fd, buf, b->i1);
+ close(fd);
+ }
+ return b->i0;
+}
+
+int
+createlevel(int n, int d)
+{+ char buf[Bufsz];
+ int i, s, fd;
+
+ s = 0;
+ for(i = 0; i < n; i++){+ snprint(buf, sizeof(buf), "%d", i);
+ if(d > 0){+ if((fd = create(buf, OWRITE, 0777|DMDIR)) == -1)
+ sysfatal("create: %r");+ if(chdir(buf) == -1)
+ sysfatal("chdir %s: %r", buf);+ s += createlevel(n, d-1);
+ chdir("..");+ }else{+ if((fd = create(buf, OWRITE, 0666)) == -1)
+ sysfatal("create: %r");+ s++;
+ }
+ close(fd);
+ }
+ return s;
+}
+
+vlong
+createhier(Bench *b)
+{+ return createlevel(b->i0, b->i1);
+}
+
+vlong
+listfiles(Bench *b)
+{+ char buf[Bufsz];
+ int i, r, fd;
+
+ for(i = 0; i < b->reps; i++){+ if((fd = open(".", OREAD)) == -1)+ sysfatal("open .: %r");+ while(1){+ if((r = read(fd, buf, sizeof(buf))) == -1)
+ sysfatal("read: %r");+ if(r == 0)
+ break;
+ }
+ close(fd);
+ }
+ return b->reps*b->i0;
+}
+
+vlong
+randopen(Bench *b)
+{+ char buf[Bufsz];
+ int i, fd;
+
+ for(i = 0; i < b->reps; i++){+ snprint(buf, sizeof(buf), "%s%lld", b->s0, vrand(b->i0));
+ if((fd = open(buf, OREAD)) == -1)
+ sysfatal("open: %r");+ if(b->i0)
+ if(read(fd, buf, sizeof(buf)) == -1)
+ sysfatal("read: %r");+ close(fd);
+ }
+ return b->reps;
+}
+
+void
+launch(void *p)
+{+ Bench *b;
+ vlong r;
+
+ b = p;
+ r = b->fn(b);
+ send(b->rc, &r);
+}
+
+vlong
+runpar(Bench *b)
+{+ vlong r, sum;
+ Bench *sub;
+ int i;
+
+ sum = 0;
+ b->rc = chancreate(sizeof(vlong), b->nproc);
+ if((sub = calloc(b->nproc, sizeof(Bench))) == nil)
+ sysfatal("malloc: %r");+ for(i = 0; i < b->nproc; i++){+ sub[i] = *b;
+ sub[i].id = i;
+ proccreate(launch, &sub[i], mainstacksize);
+ }
+ for(i = 0; i < b->nproc; i++){+ recv(b->rc, &r);
+ sum += r;
+ }
+ free(sub);
+ return sum;
+}
+
+void
+runbench(Bench *b, int nb)
+{+ char *unit[] = {"ns", "us", "ms", "s"};+ double oc, dt;
+ vlong t0, t1;
+ int i, j;
+
+ for(i = 0; i < nb; i++){+ if(b[i].reps == 0)
+ b[i].reps = 1;
+ print("%20s:\t", b[i].name);+ t0 = nsec();
+ if(b[i].nproc <= 1){+ b[i].id = -1;
+ oc = b[i].fn(&b[i]);
+ }else
+ oc = runpar(&b[i]);
+ t1 = nsec();
+ dt = (t1 - t0);
+ for(j = 0; j < nelem(unit)-1; j++)
+ if(dt/100 < 1)
+ break;
+ else
+ dt /= 1000.0;
+ print("%f%s (%f %s/%s)\n", dt, unit[j], (double)oc/dt, b[i].unit, unit[j]);+ }
+}
+
+void
+threadmain(int argc, char **argv)
+{+ Bench marks[] = {+ /* l => linear, a => aligned, r => random */
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.0"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.1"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.2"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.3"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.4"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.5"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.6"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.7"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.8"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.9"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.10"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.11"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.12"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.13"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.14"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.15"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.16"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.17"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.18"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.19"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.20"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.21"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.22"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.23"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.24"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.25"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.26"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.27"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.28"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.29"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.30"},+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.31"},+
+ {.name="rdcached_lala", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0"},+ {.name="rdcached_lara", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0"},+ {.name="rdcached_larr", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0"},+
+ {.name="rdcached_lala_2p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=2},+ {.name="rdcached_lara_2p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=2},+ {.name="rdcached_larr_2p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=2},+
+ {.name="rdcached_lala_4p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=4},+ {.name="rdcached_lara_4p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=4},+ {.name="rdcached_larr_4p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=4},+
+ {.name="rdcached_lala_8p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=8},+ {.name="rdcached_lara_8p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=8},+ {.name="rdcached_larr_8p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=8},+
+ {.name="rdcached_lala_12p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=12},+ {.name="rdcached_lara_12p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=12},+ {.name="rdcached_larr_12p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=12},+
+ {.name="rdcached_lala_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=16},+ {.name="rdcached_lara_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=16},+ {.name="rdcached_larr_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=16},+
+ {.name="rdcached_lala_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=16},+ {.name="rdcached_lara_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=16},+ {.name="rdcached_larr_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=16},+
+ {.name="rdcached_lala_16p_1f", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=16, .i1=1},+ {.name="rdcached_lara_16p_8f", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=16, .i1=8},+ {.name="rdcached_larr_32p_16f", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=32, .i1=16},+ {.name="rdcached_larr_32p_32f", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=32, .i1=32},+
+ {.name="wrcached_ra", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_ra, .s0="cached1"},+ {.name="rdcached_rala", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_la, .s0="cached1"},+ {.name="rdcached_rara", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_ra, .s0="cached1"},+ {.name="rdcached_rarr", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_rr, .s0="cached1"},+
+ {.name="wrcached_rr", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_rr, .s0="cached2"},+ {.name="rdcached_rrla", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_la, .s0="cached2"},+ {.name="rdcached_rrra", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_ra, .s0="cached2"},+ {.name="rdcached_rrrr", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_rr, .s0="cached2"},+
+ {.name="rwcached_la_r0_w2_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=2, .i1=2},+ {.name="rwcached_la_r0_w4_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=4},+ {.name="rwcached_la_r1_w1_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=2, .i1=1},+ {.name="rwcached_la_r3_w1_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=1},+ {.name="rwcached_la_r2_w2_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=2},+ {.name="rwcached_la_r6_w2_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=8, .i1=2},+ {.name="rwcached_la_r4_w4_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=8, .i1=4},+
+ {.name="rwcached_la_r1_w1_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=2, .i1=1},+ {.name="rwcached_la_r2_w1_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=3, .i1=1},+ {.name="rwcached_la_r3_w1_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=1},+ {.name="rwcached_la_r1_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=2},+ {.name="rwcached_la_r1_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=3, .i1=2},+ {.name="rwcached_la_r2_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=2},+ {.name="rwcached_la_r4_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=2},+ {.name="rwcached_la_r6_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=8, .i1=2},+ {.name="rwcached_la_r4_w4_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=8, .i1=4},+
+ {.name="createflat", .i0=100*1000, .reps=1, .unit="files", .fn=createflat, .s0="cz"},+ {.name="write1flat", .i0=100*1000, .reps=1, .unit="files", .fn=createflat, .i1=1, .s0="c1"},+ {.name="write100flat", .i0=100*1000, .reps=1, .unit="files", .fn=createflat, .i1=100, .s0="c100"},+ {.name="write1027flat", .i0=100*1000, .reps=1, .unit="files", .fn=createflat, .i1=1027, .s0="c1027"},+ {.name="listfflat", .i0=100*1000, .reps=10, .unit="files", .fn=listfiles},+ {.name="openfflat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .s0="cz"},+ {.name="read0flat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .i1=1, .s0="cz"},+ {.name="read1flat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .i1=1, .s0="c1"},+ {.name="read100flat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .i1=1, .s0="c100"},+ {.name="read1027flat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .i1=1, .s0="c1027"},+
+// {.name="rwcached_lara", .i0=512*MiB, .reps=10, .unit="MiB", .fn=rwfile_la, .s0="cached0", .i0=1, .i1=3},+// {.name="rwcached_la", .i0=512*MiB, .reps=10, .unit="MiB", .fn=rwfile_la, .s0="cached0", .i0=3, .i1=3},+// {.name="rwcached_la", .i0=512*MiB, .reps=10, .unit="MiB", .fn=rwfile_la, .s0="cached0", .i0=10, .i1=10},+
+
+ {.name="wrlarge_la", .i0=16*GiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="large0"},+ {.name="rdlarge_lala", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_la, .s0="large0"},+ {.name="rdlarge_lara", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_ra, .s0="large0"},+// {.name="rdlarge_larr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_rr, .s0="large0"},+
+ {.name="wrlarge_ra", .i0=16*GiB, .reps=1, .unit="MiB", .fn=wrfile_ra, .s0="large1"},+ {.name="rdlarge_lara", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_la, .s0="large1"},+ {.name="rdlarge_rara", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_ra, .s0="large1"},+// {.name="rdlarge_rarr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_rr, .s0="large1"},+
+// {.name="wrlarge_rr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=wrfile_rr, .s0="large2"},+// {.name="rdlarge_larr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_la, .s0="large2"},+// {.name="rdlarge_rarr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_ra, .s0="large2"},+// {.name="rdlarge_rrrr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_rr, .s0="large2"},+
+// {.name="createheir", .i0=3, .i1=10, .reps=1, .unit="files", .fn=createhier},+// {.name="openheir", .i0=3, .i1=10, .reps=1, .unit="files", .fn=randwalk},+ };
+
+ ARGBEGIN{+ }ARGEND;
+
+ if(argc != 1){+ fprint(2, "usage: %s wdir\n", argv0);
+ exits("usage");+ }
+ if(chdir(argv[0]) == -1)
+ sysfatal("chdir: %r");+ runbench(marks, nelem(marks));
+ exits(nil);
+}
--- /dev/null
+++ b/grind.rc
@@ -1,0 +1,69 @@
+#!/bin/rc
+
+dev = testdev.fs
+gefs = ../$O.out
+
+fn ream {+ mk all && 6.out -r $user -f $dev
+}
+
+fn startfs {+ $O.out -A -f $dev
+}
+
+fn endfs {+ kill $O.out | rc
+ while(test -f /n/gefs.grid)
+ sleep 0.1
+}
+
+fn build9 {@{+ rfork ne
+ m
+ cd /n/gefs
+ . /sys/lib/rootstub
+ if(! test -e plan9front)
+ git/clone /dist/plan9front
+ bind -c $objtype/lib /$objtype/lib
+ bind -c plan9front/sys/include /sys/include
+ bind -c tmp /tmp
+ cd plan9front/sys/src
+ mk clean >> /tmp/log
+ mk all >> /tmp/log
+}}
+
+fn buildself {@{+ rfork ne
+ m
+ cd /n/gefs
+ if(! test -e gefs)
+ git/clone $home/src/gefs
+ cd gefs
+ mk clean > /tmp/log
+ mk all > /tmp/log
+}}
+
+fn replay_fast {+ ream
+ mount -c
+
+ build9
+ endfs
+}
+
+fn replay_slow {+}
+
+fn filldisk {+}
+
+fn lotsa9 {+}
+
+fn lotsaself {+}
+
+dev = testdev.fs
+rm -f $dev
+dd -if /dev/zero -of $dev -bs 1kk -count 512
+replay_fast
\ No newline at end of file
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,15 @@
+</$objtype/mkfile
+
+TESTS=\
+ basic\
+ build\
+
+all:V: 6.freplay 6.fsbench
+
+test:VQ:
+ @{cd .. && mk 6.out}+ for(t in $TESTS){+ echo $t...
+ ./$t.rc >[2=1] >$t.log
+ }
+</sys/src/cmd/mktest
--- /dev/null
+++ b/mkgefs.rc
@@ -1,0 +1,8 @@
+#!/bin/rc
+
+@{cd .. && mk all}+../6.out -r $user -f $1
+../6.out -n gefs.test -A -m 2048 -f $1
+
+mount -c /srv/gefs.test /n/gefs
+mount -c /srv/gefs.test /n/gefs.adm adm
--- /dev/null
+++ b/psnap.rc
@@ -1,0 +1,45 @@
+#!/bin/rc -e
+
+
+srv=/srv/gefs
+if(~ $#* 1)
+ srv=$1
+
+fn cloneto {+ echo clone to $1
+ @{cd /n/gefs.$1 && git/clone /dist/plan9front}+ echo clone $1 done
+}
+
+fn buildin {+ @{+ rfork n
+ cd /n/gefs.$1/plan9front/
+ . /sys/lib/rootstub
+ bind -c sys/include /sys/include
+ bind -c $objtype/lib /$objtype/lib
+ bind -bc $objtype/bin /bin
+ bind -bc $objtype/bin /$objtype/bin
+ cd sys/src
+ mk all >[2=1] >/tmp/ptest.$1.log
+ }
+}
+
+echo 'create snap'
+echo 'snap -m empty test1' >> $srv.cmd
+echo 'snap -m empty test2' >> $srv.cmd
+echo 'sync' >> $srv.cmd
+mount -c $srv /n/gefs.a test1
+mount -c $srv /n/gefs.b test2
+
+echo 'clone repos'
+cloneto a &
+cloneto b &
+wait
+
+echo 'build repos'
+buildin a &
+buildin b &
+wait
+
+echo 'done'
--- /dev/null
+++ b/run.rc
@@ -1,0 +1,187 @@
+#!/bin/rc
+
+rfork ne
+
+dev=$testdev
+if(~ $#testdev 0)
+ dev = testdev.fs
+switch($cputype){+case amd64; O=6
+case arm64; O=7
+case arm; O=5
+case 386; O=8
+}
+
+fn sigexit sigint {+ rm -f /srv/gefs.test /srv/gefs.test.cmd /srv/replay
+}
+
+fn die {+ echo $* >[1=2]
+ exit $"*
+}
+
+fn log {+ echo $* >[1=2]
+}
+
+fn ge_ream {+ $O.out -m 512 -r $user -f $1
+}
+
+fn ge_start {+ $O.out -m 512 -A -f $1 -n gefs.test
+ while(! test -e /srv/gefs.test)
+ sleep 0.1
+ mount -c /srv/gefs.test /n/gefs
+}
+
+fn ge_kill {+ kill $O.out | rc
+ while(test -e /srv/gefs.test)
+ sleep 0.1
+}
+
+fn ge_replay {@{+ # prepare the test run
+ log reaming...
+ ge_ream $dev
+ log preparing replay...
+ rm -f replay.log
+ test/6.freplay -l replay.log $dev
+ ge_start /mnt/replay/data
+ $*
+ echo save trace /tmp/trace >> /srv/gefs.test.cmd
+ sleep 5
+ ge_kill
+ cat /mnt/replay/ctl
+ count=`{awk '/writes/{print $2}' /mnt/replay/ctl}+ log did $count writes.
+ echo exit > /mnt/replay/ctl
+ while(test -e /srv/replay)
+ sleep 0.1
+
+ # check blockwise consistency
+ log starting replay...
+ test/6.freplay -c 1 -r replay.log $dev
+ for(i in `{seq 2 $count}){+ $O.out -c -f /mnt/replay/data >[2]/tmp/log || die 'broken'
+ log stepping $i...
+ echo step > /mnt/replay/ctl
+ }
+ echo exit > /mnt/replay/ctl
+ while(test -e /srv/replay)
+ sleep 0.1
+ exit ''
+}}
+
+fn ge_ok {@{+ # prepare the test run
+ log reaming...
+ ge_ream $dev
+ log preparing build-and-verify...
+ test/6.freplay -l replay.log $dev
+ ge_start $dev
+ $*
+ echo save trace /tmp/trace >> /srv/gefs.test.cmd
+ ge_kill
+ $O.out -c -f $dev
+}}
+
+fn buildsys{@{+ rfork ne
+ cd /n/gefs
+ . /sys/lib/rootstub
+ if(! test -e plan9front)
+ git/clone /dist/plan9front
+ bind -c $objtype/lib /$objtype/lib
+ bind -c plan9front/sys/include /sys/include
+ bind -c tmp /tmp
+ cd plan9front/sys/src
+ mk clean >> /tmp/gefsbuild.log
+ mk all >> /tmp/gefsbuild.log
+ echo save trace >> /srv/gefs.test.cmd
+ echo check >> /srv/gefs.test.cmd
+}}
+
+fn frobsnap {@{+ rfork ne
+ sleep 1; echo snap main x >> /srv/gefs.test.cmd
+ sleep 1; dd -if /dev/zero -of /n/gefs/file0 -bs 16k -count 128
+ sleep 1; echo snap main y >> /srv/gefs.test.cmd;
+ sleep 1; dd -if /dev/zero -of /n/gefs/file1 -bs 16k -count 128
+ sleep 1; echo snap main z >> /srv/gefs.test.cmd;
+ sleep 1; rm /n/gefs/^(file0 file1);
+ sleep 1; echo snap -d y >> /srv/gefs.test.cmd;
+ sleep 1; echo check >> /srv/gefs.test.cmd
+ sleep 1; echo snap -d z >> /srv/gefs.test.cmd;
+ sleep 1; echo check >> /srv/gefs.test.cmd
+ sleep 1; echo snap -d x >> /srv/gefs.test.cmd;
+ sleep 1; echo check >> /srv/gefs.test.cmd
+}}
+
+fn buildgo {@{+ rfork ne
+ GOROOT=/n/gefs/go
+ GOROOT_BOOTSTRAP=/n/gefs/go-plan9-amd64-bootstrap
+ go=go1.17.13-plan9-$cputype-bootstrap
+
+ cd /n/gefs
+ if(! test -e /tmp/$go.tbz){+ echo getting https://9legacy.org/download/go/$go.tbz ...
+ hget -o /tmp/$go.tbz https://9legacy.org/download/go/$go.tbz
+ }
+ if(! test -e $GOROOT_BOOTSTRAP){+ echo extracting /tmp/$go.tbz ...
+ bunzip2 -c /tmp/$go.tbz | tar x >[2]/dev/null
+ }
+ mkdir go
+ mkdir tmpw
+ dircp go-plan9-amd64-bootstrap go
+ bind -c tmp /tmp
+ cd go/src
+ ./all.rc
+}}
+
+fn buildgefs {@{+ cd /n/gefs
+ if(! test -e gefs)
+ git/clone $home/src/gefs
+ cd gefs
+ mk clean > /tmp/gefsbuild.log
+ mk all > /tmp/gefsbuild.log
+ echo check >> /srv/gefs.test.cmd
+}}
+
+fn buildgefs_slowrep {+ for(i in `{seq $1}){+ echo @@ buildgefs $i
+ buildgefs
+ sleep 10
+ }
+}
+
+fn fillfs {+ dd -if /dev/zero -of /n/gefs/stuff
+}
+
+fn dotest {+ rm -f /tmp/gefs.log /tmp/gefsbuild.log
+ echo $*
+ $* || die $status
+}
+
+if(! test -e $dev)
+ dd -if /dev/zero -of $dev -bs 1kk -count 2k
+rm -f /srv/gefs.test /srv/gefs.test.cmd /srv/replay
+mk all
+@{cd test && mk all}+
+dotest ge_replay frobsnap
+dotest ge_replay buildgefs_slowrep 50
+dotest ge_ok buildsys
+dotest ge_ok fillfs
+
+# disabled by default: go doesn't fit into a
+# small fs; make a bigger one for testing.
+# dotest ge_ok buildgo
--
⑨