ref: 48a546aeb35a92612019402466507e1910c00f81
parent: 36ca89c4363a46ab0d7d2d562f92e92c4ba81063
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Jul 13 18:35:35 EDT 2025
fsio: add initial set of fs benchmarks
--- /dev/null
+++ b/fsio.c
@@ -1,0 +1,257 @@
+#include <u.h>
+#include <libc.h>
+
+#include "bench.h"
+
+char *benchdir;
+char randbuf[128*IOUNIT];
+
+enum {
+ KiB = 1024,
+ MiB = 1024*KiB,
+ GiB = 1024*MiB,
+};
+
+#define Nfiles 8
+#define Filesz 128*MiB
+
+void
+setup(void)
+{
+ char path[512], buf[IOUNIT];
+ int i, j, n, nrd;
+ int rfd, wfd;
+
+ if((rfd = open("/dev/random", OREAD)) == -1)
+ sysfatal("open: %r");
+ readn(rfd, randbuf, sizeof(randbuf));
+ for(i = 0; i < Nfiles; i++){
+ snprint(path, sizeof(path), "%s/rfile.%d", benchdir, i);
+ if((wfd = create(path, OWRITE, 0666)) == -1)
+ sysfatal("create %s: %r", path);
+ for(j = 0; j < Filesz; j += n){
+ nrd = Filesz - j;
+ if(nrd > sizeof(buf))
+ nrd = sizeof(buf);
+ if((n = readn(rfd, buf, nrd)) != nrd)
+ sysfatal("short read");
+ if(write(wfd, buf, n) != n)
+ sysfatal("short write");
+ }
+ close(wfd);
+ }
+ close(rfd);
+}
+
+void
+cleanup(void)
+{
+ char buf[512];
+ int i, n, fd;
+ Dir *d;
+
+ if((fd = open(benchdir, OREAD)) == -1)
+ sysfatal("open %s: %r", benchdir);
+ n = dirreadall(fd, &d);
+ for(i = 0; i < n; i++){
+ snprint(buf, sizeof(buf), "%s/%s", benchdir, d[i].name);
+ remove(buf);
+ }
+ close(fd);
+}
+
+void
+dowrite(int nops, int i, int fsz, int wsz)
+{
+ int fd, j, k, n;
+ char path[512];
+
+ snprint(path, sizeof(path), "%s/write.%d.%d", benchdir, i, getpid());
+ if((fd = create(path, OWRITE, 0666)) == -1)
+ sysfatal("create: %r");
+ for(j = 0; j < nops; j++)
+ for(k = 0; k < fsz; k += n)
+ if((n = write(fd, randbuf, wsz)) != wsz)
+ sysfatal("write: %r");
+ close(fd);
+ remove(path);
+}
+
+void
+writefile(B *b, int npar, int fsz)
+{
+ int i, wsz;
+
+ wsz = fsz < IOUNIT ? fsz : IOUNIT;
+ for(i = 0; i < npar; i++){
+ switch(rfork(RFPROC|RFMEM)){
+ case -1:
+ sysfatal("fork: %r");
+ case 0:
+ dowrite(b->N/npar, i, fsz, wsz);
+ exits(nil);
+ default:
+ /* nothing */
+ break;
+ }
+ }
+ for(i = 0; i < npar; i++)
+ free(wait());
+}
+
+void
+doread(int nops, int i, int fsz, int rsz)
+{
+ char path[512], buf[IOUNIT];
+ int fd, j, k, n;
+
+ snprint(path, sizeof(path), "%s/rfile.%d", benchdir, i);
+ if((fd = open(path, OREAD)) == -1)
+ sysfatal("open: %r");
+ for(j = 0; j < nops; j++){
+ seek(fd, 0, 0);
+ for(k = 0; k < fsz; k += n)
+ if((n = readn(fd, buf, rsz)) != rsz)
+ sysfatal("read %s [%d < %d]: %r", path, n, rsz);
+ }
+ close(fd);
+}
+
+void
+readfile(B *b, int npar, int fsz)
+{
+ int i, rsz;
+
+ rsz = fsz < IOUNIT ? fsz : IOUNIT;
+ for(i = 0; i < npar; i++){
+ switch(rfork(RFPROC|RFMEM)){
+ case -1:
+ sysfatal("fork: %r");
+ case 0:
+ doread(b->N/npar, i, fsz, rsz);
+ exits(nil);
+ default:
+ /* nothing */
+ break;
+ }
+ }
+ for(i = 0; i < npar; i++)
+ free(wait());
+}
+
+void
+mixedfile(B *b, int nrd, int nwr, int fsz)
+{
+ int i, sz;
+
+ sz = fsz < IOUNIT ? fsz : IOUNIT;
+ for(i = 0; i < nrd+nwr; i++){
+ switch(rfork(RFPROC|RFMEM)){
+ case -1:
+ sysfatal("fork: %r");
+ case 0:
+ if(i < nrd)
+ doread(b->N/nrd, i, fsz, sz);
+ else
+ dowrite(b->N/nwr, i, fsz, sz);
+ exits(nil);
+ default:
+ /* nothing */
+ break;
+ }
+ }
+ for(i = 0; i < nrd+nwr; i++)
+ free(wait());
+}
+
+void writefile_p1_16b(B *b){ writefile(b, 1, 16); }
+void writefile_p2_16b(B *b){ writefile(b, 2, 16); }
+void writefile_p4_16b(B *b){ writefile(b, 4, 16); }
+void writefile_p8_16b(B *b){ writefile(b, 8, 16); }
+
+void writefile_p1_16k(B *b){ writefile(b, 1, 16*KiB); }
+void writefile_p2_16k(B *b){ writefile(b, 2, 16*KiB); }
+void writefile_p4_16k(B *b){ writefile(b, 4, 16*KiB); }
+void writefile_p8_16k(B *b){ writefile(b, 8, 16*KiB); }
+
+void writefile_p1_16m(B *b){ writefile(b, 1, 16*MiB); }
+void writefile_p2_16m(B *b){ writefile(b, 2, 16*MiB); }
+void writefile_p4_16m(B *b){ writefile(b, 4, 16*MiB); }
+void writefile_p8_16m(B *b){ writefile(b, 8, 16*MiB); }
+
+void readfile_p1_16b(B *b){ readfile(b, 1, 16); }
+void readfile_p2_16b(B *b){ readfile(b, 2, 16); }
+void readfile_p4_16b(B *b){ readfile(b, 4, 16); }
+void readfile_p8_16b(B *b){ readfile(b, 8, 16); }
+
+void readfile_p1_16k(B *b){ readfile(b, 1, 16*KiB); }
+void readfile_p2_16k(B *b){ readfile(b, 2, 16*KiB); }
+void readfile_p4_16k(B *b){ readfile(b, 4, 16*KiB); }
+void readfile_p8_16k(B *b){ readfile(b, 8, 16*KiB); }
+
+void readfile_p1_16m(B *b){ readfile(b, 1, 16*MiB); }
+void readfile_p2_16m(B *b){ readfile(b, 2, 16*MiB); }
+void readfile_p4_16m(B *b){ readfile(b, 4, 16*MiB); }
+void readfile_p8_16m(B *b){ readfile(b, 8, 16*MiB); }
+
+void mixedfile_p2(B *b){ mixedfile(b, 1, 1, 16); }
+void mixedfile_p4(B *b){ mixedfile(b, 2, 2, 16); }
+void mixedfile_p8(B *b){ mixedfile(b, 4, 4, 16); }
+
+void
+main(int argc, char **argv)
+{
+ benchinit(argc, argv);
+
+ benchdir = getenv("benchdir");
+ if(benchdir == nil){
+ fprint(2, "no benchdir: skipping\n");
+ exits(nil);
+ }
+ setup();
+ print("== file writes (16b) ==\n");
+ BM(writefile_p1_16b);
+ BM(writefile_p2_16b);
+ BM(writefile_p4_16b);
+ BM(writefile_p8_16b);
+
+ print("== file writes (16k) ==\n");
+ BM(writefile_p1_16k);
+ BM(writefile_p2_16k);
+ BM(writefile_p4_16k);
+ BM(writefile_p8_16k);
+
+ print("== file writes (16m) ==\n");
+ BM(writefile_p1_16m);
+ BM(writefile_p2_16m);
+ BM(writefile_p4_16m);
+ BM(writefile_p8_16m);
+
+ print("== file reads (16b) ==\n");
+ BM(readfile_p1_16b);
+ BM(readfile_p2_16b);
+ BM(readfile_p4_16b);
+ BM(readfile_p8_16b);
+
+ print("== file reads (16k) ==\n");
+ BM(readfile_p1_16k);
+ BM(readfile_p2_16k);
+ BM(readfile_p4_16k);
+ BM(readfile_p8_16k);
+
+ print("== file reads (16m) ==\n");
+ BM(readfile_p1_16m);
+ BM(readfile_p2_16m);
+ BM(readfile_p4_16m);
+ BM(readfile_p8_16m);
+
+ print("== mixed ops ==\n");
+ BM(mixedfile_p2);
+ BM(mixedfile_p4);
+ BM(mixedfile_p8);
+
+ cleanup();
+
+ exits(nil);
+}
+
--- a/mkfile
+++ b/mkfile
@@ -6,6 +6,7 @@
lock\
spawn\
fcall\
+ fsio\
OFILES=\
bench.$O\
--
⑨