shithub: bench9

Download patch

ref: 1046ee01c738fea18079cfbb2eb305b1e572b03b
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Oct 27 20:04:40 EDT 2020

first

--- /dev/null
+++ b/b.c
@@ -1,0 +1,186 @@
+#include <u.h>
+#include <libc.h>
+#include <tos.h>
+#include "b.h"
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+enum {
+	Btime = 1000000000ULL/10ULL,
+	Bstepmin = 100,
+};
+
+static uvlong adj;
+
+uvlong
+cycles2ns(uvlong x)
+{
+	uvlong div;
+
+	/* this is ugly */
+	for(div = 1000000000ULL; x < 0x1999999999999999ULL && div > 1 ; div /= 10ULL, x *= 10ULL);
+
+	return x / (_tos->cyclefreq / div);
+}
+
+static int
+σfmt(Fmt *f)
+{
+	B *b;
+	uvlong nsall;
+
+	b = va_arg(f->args, B*);
+	nsall = cycles2ns(b->tout - b->t0);
+
+	return fmtprint(f, "%zd", nsall/b->med.ns);
+}
+
+static int
+τfmt(Fmt *f)
+{
+	Cns c;
+
+	c = va_arg(f->args, Cns);
+
+	return fmtprint(f,	"%zd", c.ns);
+}
+
+void
+benchinit(B *b, char *name)
+{
+	int i;
+
+	fmtinstall(L'σ', σfmt);
+	fmtinstall(L'τ', τfmt);
+	memset(b, 0, sizeof(*b));
+	b->name = name;
+	b->n = b->nc = Bstepmin;
+	b->min.c--;
+	b->c = mallocz(b->nc * sizeof(*b->c), 1);
+
+	if(adj == 0){
+		uvlong v;
+		for(i = 0, v = 0; i < 100; i++){
+			uvlong s, e;
+			_tstart(&s);
+			_tend(&e);
+			v += e - s;
+		}
+		adj = v / i;
+	}
+}
+
+static int
+ccmp(void *a, void *b)
+{
+	u32int *x, *y;
+
+	x = a;
+	y = b;
+
+	return *x < *y ? -1 : (*x > *y ? 1 : 0);
+}
+
+static void
+benchcalc(B *b)
+{
+	uvlong m;
+
+	qsort(b->c, b->ic, sizeof(*b->c), ccmp);
+
+	if(b->ic & 1)
+		m = b->c[b->ic/2];
+	else
+		m = (b->c[b->ic/2-1] + b->c[b->ic/2])/2;
+	b->med.ns = cycles2ns(b->med.c = m);
+	b->avg.ns = cycles2ns(b->avg.c = b->tot.c / b->step);
+	b->min.ns = cycles2ns(b->min.c = b->c[0]);
+	b->max.ns = cycles2ns(b->max.c = b->c[b->ic-1]);
+	b->p96.ns = cycles2ns(b->c[b->ic*96 / 100]);
+	b->p98.ns = cycles2ns(b->c[b->ic*98 / 100]);
+	b->p99.ns = cycles2ns(b->c[b->ic*99 / 100]);
+}
+
+void
+benchstep(B *b)
+{
+	uvlong c;
+
+	if(b->step == 0)
+		b->t0 = b->tin;
+	b->step++;
+	b->n--;
+
+	if(b->tout <= b->tin)
+		sysfatal("%zd ≤ %zd → t₁ ≤ t₀", b->tout, b->tin);
+	if(b->tout - b->tin < adj) /* sometimes this happens */
+		adj = b->tout - b->tin;
+	c = b->tout - b->tin - adj;
+	if(b->ic >= b->nc){
+		b->nc *= 2;
+		b->c = realloc(b->c, b->nc * sizeof(*b->c));
+		memset(b->c+b->ic, 0, sizeof(*b->c)*(b->nc - b->ic));
+	}
+	b->c[b->ic++] = c;
+
+	b->tot.c += c;
+	b->tot.ns = cycles2ns(b->tot.c);
+
+	if(b->n == 0){
+		uvlong nsall = cycles2ns(b->tout - b->t0);
+		if(nsall < Btime)
+			b->n = (Btime - nsall) / (nsall / b->step);
+		if(b->n == 0){
+			benchcalc(b);
+			free(b->c);
+		}
+	}
+}
+
+void
+benchprint(B *b, int nb, int fd)
+{
+	static char *header[] = {"   ", "op/s", "99%", "98%", "96%", "med", "avg", "min"};
+	static int w[] = {16, 8, 8, 8, 8, 8, 8, 8};
+	static int off[] = {
+		0,
+		0,
+		offsetof(B, p99),
+		offsetof(B, p98),
+		offsetof(B, p96),
+		offsetof(B, med),
+		offsetof(B, avg),
+		offsetof(B, min),
+	};
+	char t[32], *s, *p;
+	int i, j, n;
+
+	for(i = 0; i < nb; i++){
+		w[0] = MAX(w[0], snprint(t, sizeof(t), "%s  ", b[i].name ? b[i].name : ""));
+		w[1] = MAX(w[1], snprint(t, sizeof(t), "%σ  ", &b[i]));
+		for(j = 2; j < nelem(header); j++)
+			w[j] = MAX(w[j], snprint(t, sizeof(t), "%τ  ", *(Cns*)((char*)(b+i) + off[j])));
+	}
+
+	for(j = n = 0; j < nelem(header); j++)
+		n += w[j];
+	s = malloc(n+1);
+	memset(s, ' ', n);
+	for(j = 0, p = s; j < nelem(header); p += w[j++])
+		p[sprint(p, "%s", header[j])] = ' ';
+	*p = 0;
+	fprint(fd, "%s\n", s);
+
+	for(i = 0; i < nb; i++){
+		memset(s, ' ', n);
+		p = s;
+		p[sprint(p, "%s  ", b[i].name)] = ' ';
+		p += w[0];
+		p[snprint(p, sizeof(t), "%σ  ", &b[i])] = ' ';
+		p += w[1];
+		for(j = 2; j < nelem(header); p += w[j], j++)
+			p[sprint(p, "%τ  ", *(Cns*)((char*)(b+i) + off[j]))] = ' ';
+		*p = 0;
+		fprint(fd, "%s\n", s);
+	}
+}
--- /dev/null
+++ b/b.h
@@ -1,0 +1,34 @@
+typedef struct B B;
+typedef struct Cns Cns;
+
+struct Cns {
+	uvlong c;
+	uvlong ns;
+};
+
+#pragma varargck type "σ" B*
+#pragma varargck type "τ" Cns
+
+struct B {
+	uvlong n;
+	uvlong tin;
+	uvlong tout;
+	uvlong step;
+	uvlong t0;
+	Cns tot, avg, med, min, max;
+	Cns p96, p98, p99;
+	u32int *c;
+	int nc, ic;
+	char *name;
+};
+
+/* private */
+void benchstep(B *b);
+void _tstart(uvlong *c);
+void _tend(uvlong *c);
+
+/* public */
+void benchinit(B *b, char *name);
+void benchprint(B *b, int nb, int fd);
+#define benchin(b) do{ _tstart(&(b)->tin); }while(0)
+#define benchout(b) do{ _tend(&(b)->tout); benchstep(b); }while(0)
--- /dev/null
+++ b/b_amd64.s
@@ -1,0 +1,13 @@
+TEXT _tstart(SB), 1, $0
+	LFENCE
+	RDTSC
+	MOVL AX, 0(RARG)
+	MOVL DX, 4(RARG)
+	RET
+
+TEXT _tend(SB), 1, $0
+	RDTSC
+	MOVL AX, 0(RARG)
+	MOVL DX, 4(RARG)
+	CPUID
+	RET
--- /dev/null
+++ b/main.c
@@ -1,0 +1,123 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include "b.h"
+
+static void
+proc(void *)
+{
+	threadexits(nil);
+}
+
+void
+threadmain(int argc, char **argv)
+{
+	B group[10], *b;
+	uchar d[1];
+	int f;
+
+	ARGBEGIN{
+	}ARGEND
+
+	b = &group[0];
+
+	f = open("/dev/null", OREAD);
+	benchinit(b, "read/1");
+	while(b->n > 0){
+		benchin(b);
+		read(f, d, 1);
+		benchout(b);
+	}
+
+	b++;
+	benchinit(b, "read/0");
+	while(b->n > 0){
+		benchin(b);
+		read(f, d, 0);
+		benchout(b);
+	}
+	close(f);
+
+	b++;
+	benchinit(b, "sin(n)");
+	while(b->n > 0){
+		benchin(b);
+		sin(b->n);
+		benchout(b);
+	}
+
+	b++;
+	benchinit(b, "cos(n)");
+	while(b->n > 0){
+		benchin(b);
+		cos(b->n);
+		benchout(b);
+	}
+
+	b++;
+	benchinit(b, "tan(n)");
+	while(b->n > 0){
+		benchin(b);
+		tan(b->n);
+		benchout(b);
+	}
+
+	b++;
+	benchinit(b, "sleep(0)");
+	while(b->n > 0){
+		benchin(b);
+		sleep(0);
+		benchout(b);
+	}
+
+	b++;
+	benchinit(b, "proccreate");
+	while(b->n > 0){
+		benchin(b);
+		proccreate(proc, (void*)b->n, 1024);
+		benchout(b);
+	}
+
+	b++;
+	benchinit(b, "memmove(4k)");
+	while(b->n > 0){
+		char *x, *y;
+		x = malloc(4096);
+		y = malloc(4096);
+		benchin(b);
+		memmove(x, y, 4096);
+		benchout(b);
+		free(x);
+		free(y);
+	}
+
+	b++;
+	benchinit(b, "memmove(64k)");
+	while(b->n > 0){
+		char *x, *y;
+		x = malloc(65536);
+		y = malloc(65536);
+		benchin(b);
+		memmove(x, y, 65536);
+		benchout(b);
+		free(x);
+		free(y);
+	}
+
+	b++;
+	benchinit(b, "memmove(256k)");
+	while(b->n > 0){
+		char *x, *y;
+		x = malloc(256*1024);
+		y = malloc(256*1024);
+		benchin(b);
+		memmove(x, y, 256*1024);
+		benchout(b);
+		free(x);
+		free(y);
+	}
+
+	benchprint(group, nelem(group), 1);
+
+	threadexitsall(nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,16 @@
+</$objtype/mkfile
+
+TARG=bench9
+BIN=/$objtype/bin
+
+HFILES=\
+	b.h\
+
+OFILES=\
+	b.$O\
+	b_$objtype.$O\
+	main.$O\
+
+default:V: all
+
+</sys/src/cmd/mkone