ref: 10751c463369951caaa071b1a3e1ea0d3b20f30a
dir: /test/fsbench.c/
#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 buf[Bufsz]; vlong i, rep; int fd; if((fd = open(b->s0, 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 buf[Bufsz]; vlong i, rep; uvlong off; int fd; if((fd = open(b->s0, 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) & ~(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; vlong r; 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 buf[Bufsz]; vlong i, rep; uvlong off; int fd; if((fd = open(b->s0, 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%d", 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=256*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0"}, {.name="rdcached_lala", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0"}, {.name="rdcached_lara", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0"}, {.name="rdcached_larr", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0"}, {.name="rdcached_lala_2p", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=2}, {.name="rdcached_lara_2p", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=2}, {.name="rdcached_larr_2p", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=2}, {.name="rdcached_lala_4p", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=4}, {.name="rdcached_lara_4p", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=4}, {.name="rdcached_larr_4p", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=4}, {.name="rdcached_lala_8p", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=8}, {.name="rdcached_lara_8p", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=8}, {.name="rdcached_larr_8p", .i0=256*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=8}, {.name="wrcached_ra", .i0=256*MiB, .reps=1, .unit="MiB", .fn=wrfile_ra, .s0="cached1"}, {.name="rdcached_rala", .i0=256*MiB, .reps=10, .unit="MiB", .fn=rdfile_la, .s0="cached1"}, {.name="rdcached_rara", .i0=256*MiB, .reps=10, .unit="MiB", .fn=rdfile_ra, .s0="cached1"}, {.name="rdcached_rarr", .i0=256*MiB, .reps=10, .unit="MiB", .fn=rdfile_rr, .s0="cached1"}, {.name="wrcached_rr", .i0=256*MiB, .reps=1, .unit="MiB", .fn=wrfile_rr, .s0="cached2"}, {.name="rdcached_rrla", .i0=256*MiB, .reps=10, .unit="MiB", .fn=rdfile_la, .s0="cached2"}, {.name="rdcached_rrra", .i0=256*MiB, .reps=10, .unit="MiB", .fn=rdfile_ra, .s0="cached2"}, {.name="rdcached_rrrr", .i0=256*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="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="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="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); }