shithub: mc

Download patch

ref: 7ef09f3db883c42d01e3b1d80f0d2da6ceff9913
parent: 40d6f7b5cc0cb9e5de1675a1441ad0dfc0a66bda
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Sep 3 22:58:44 EDT 2017

Modernize benchmarks.

--- a/Makefile
+++ b/Makefile
@@ -18,8 +18,7 @@
 
 .PHONY: bench
 bench:
-	mbld -tbench
-	mbld -tbench bench:benchit
+	mbld bench
 
 .PHONY: bootstrap
 bootstrap: buildmyr
--- a/bench/bigfactorial.myr
+++ b/bench/bigfactorial.myr
@@ -1,11 +1,13 @@
 use std
+use testr
 
-const N = 600
 const main = {
-	var i
-	for i = 0; i < N; i++
-		std.bigfree(bigfact(i))
-	;;
+	testr.bench([
+		[.name="bigfactorial-1", .fn={ctx; bigfact(1)}],
+		[.name="bigfactorial-100", .fn={ctx; bigfact(100)}],
+		[.name="bigfactorial-1000", .fn={ctx; bigfact(1000)}],
+		[.name="bigfactorial-10000", .fn={ctx; bigfact(10000)}],
+	][:])
 }
 
 const bigfact = {n
--- a/bench/bld.sub
+++ b/bench/bld.sub
@@ -1,57 +1,30 @@
-bin intsort {noinst,tag=bench} =
-	intsort.myr
+testdeps =
 	lib ../lib/std:std
 	lib ../lib/sys:sys
+	lib ../lib/crypto:crypto
+	lib ../lib/bio:bio
+	lib ../lib/testr:testr
 ;;
-bin copious-allocs {noinst,tag=bench} =
+
+bench intsort =
+	intsort.myr
+;;
+bench copious-allocs =
 	copious-allocs.myr
-	lib ../lib/std:std
-	lib ../lib/sys:sys
 ;;
-bin sha1-compute {noinst,tag=bench} =
+bench sha1-compute =
 	sha1-compute.myr
-	lib ../lib/std:std
-	lib ../lib/sys:sys
-	lib ../lib/crypto:crypto
 ;;
-bin bigfactorial {noinst,tag=bench} =
+bench bigfactorial =
 	bigfactorial.myr
-	lib ../lib/std:std
-	lib ../lib/sys:sys
 ;;
-bin mandelbrot {noinst,tag=bench} =
+bench mandelbrot =
 	mandelbrot.myr
-	lib ../lib/std:std
-	lib ../lib/sys:sys
-	lib ../lib/bio:bio
 ;;
-bin regex-match {noinst,tag=bench} =
+bench regex-match =
 	regex-match.myr
-	lib ../lib/std:std
-	lib ../lib/sys:sys
-	lib ../lib/regex:regex
 ;;
 
-bin many-memcpy {noinst,tag=bench} =
+bench many-memcpy =
 	many-memcpy.myr
-	lib ../lib/std:std
-	lib ../lib/sys:sys
-;;
-
-# benchmark runner
-bin runbench {noinst,tag=bench} =
-	runbench.myr
-	lib ../lib/std:std
-	lib ../lib/sys:sys
-;;
-
-cmd benchit {tag=bench} =
-	./runbench
-		intsort
-		copious-allocs 
-		sha1-compute
-		bigfactorial
-		mandelbrot
-		regex-match
-		many-memcpy
 ;;
--- a/bench/copious-allocs.myr
+++ b/bench/copious-allocs.myr
@@ -1,4 +1,5 @@
 use std
+use testr
 
 type blob = struct
 	x : int[10]
@@ -5,33 +6,55 @@
 ;;
 
 const main = {
+	testr.bench([
+		[.name="alloc-one", .fn=alloc_one],
+		[.name="allocmany-fwdfwd", .fn=alloc_fwdfwd],
+		[.name="allocmany-fwdrev", .fn=alloc_fwdrev],
+		[.name="allocmany-fwdrand", .fn=alloc_fwdrand],
+	][:])
+}
+
+const alloc_one = {ctx
+	var a : int#
+	a = std.alloc()
+	std.free(a)
+}
+
+const alloc_fwdfwd = {ctx
 	var a : blob#[10000]
 
-	for var j = 0; j < 100; j++
-		/* alloc forwards, dealloc forwards */
-		for var i = 0; i < a.len; i++
-			a[i] = std.alloc()
-		;;
-		for var i = 0; i < a.len; i++
-			std.free(a[i])
-		;;
+	/* alloc forwards, dealloc forwards */
+	for var i = 0; i < a.len; i++
+		a[i] = std.alloc()
+	;;
+	for var i = 0; i < a.len; i++
+		std.free(a[i])
+	;;
 
-		/* alloc forwards, dealloc backwards */
-		for var i = 0; i < a.len; i++
-			a[i] = std.alloc()
-		;;
-		for var i = a.len; i > 0; i--
-			std.free(a[i - 1])
-		;;
+}
 
-		/* alloc forwards, dealloc randomly */
-		for var i = 0; i < a.len; i++
-			a[i] = std.alloc()
-		;;
-		shuffle(a[:])
-		for var i = a.len; i > 0; i--
-			std.free(a[i - 1])
-		;;
+const alloc_fwdrev = {ctx
+	var a : blob#[10000]
+
+	/* alloc forwards, dealloc backwards */
+	for var i = 0; i < a.len; i++
+		a[i] = std.alloc()
+	;;
+	for var i = a.len; i > 0; i--
+		std.free(a[i - 1])
+	;;
+}
+
+const alloc_fwdrand = {ctx
+	var a : blob#[10000]
+
+	/* alloc forwards, dealloc randomly */
+	for var i = 0; i < a.len; i++
+		a[i] = std.alloc()
+	;;
+	shuffle(a[:])
+	for var i = a.len; i > 0; i--
+		std.free(a[i - 1])
 	;;
 }
 
--- a/bench/intsort.myr
+++ b/bench/intsort.myr
@@ -1,6 +1,13 @@
 use std
+use testr
 
 const main = {
+	testr.bench([
+		[.name="fill-sort", .fn={ctx; benchsort()}]
+	][:])
+}
+
+const benchsort = {
 	var a, i
 
 	a = std.slalloc(500_000)
@@ -8,4 +15,5 @@
 		a[i] = std.randnum()
 	;;
 	std.sort(a, std.numcmp)
+	std.slfree(a)
 }
--- a/bench/mandelbrot.myr
+++ b/bench/mandelbrot.myr
@@ -1,9 +1,39 @@
 use std
 use bio
+use testr
 
 const Bailout : flt64 = 16.0
 const Maxiter = 1000
 
+const main = {
+	testr.bench([
+		[.name="mandelbrot", .fn=writemandel]
+	][:])
+}
+
+
+const writemandel = {ctx
+	var x : flt64, y : flt64, i
+	var f
+
+	f = bio.mkfile(1, bio.Wr)
+	for i = 0; i < 10; i++
+		for y = -39.0; y < 39.0; y = y + 1.0
+			for x = -39.0; x < 39.0; x = x + 1.0
+				if mandelbrot(x/40.0, y/40.0) == 0
+					bio.write(f, "*")
+				else
+					bio.write(f, " ")
+				;;
+			;;
+			bio.write(f, "\n")
+		;;
+	;;
+	bio.write(f, "\n")
+	/* we still use this fd to log our test output... */
+	bio.flush(f)
+}
+
 const mandelbrot = {x, y
 	var cr, ci, zr, zi
 	var tmp, zr2, zi2
@@ -31,25 +61,4 @@
 		;;
 	;;
 	-> 0
-}
-
-const main = {args : byte[:][:]
-	var x : flt64, y : flt64, i
-	var f
-
-	f = bio.mkfile(1, bio.Wr)
-	for i = 0; i < 10; i++
-		for y = -39.0; y < 39.0; y = y + 1.0
-			for x = -39.0; x < 39.0; x = x + 1.0
-				if mandelbrot(x/40.0, y/40.0) == 0
-					bio.write(f, "*")
-				else
-					bio.write(f, " ")
-				;;
-			;;
-			bio.write(f, "\n")
-		;;
-	;;
-	bio.write(f, "\n")
-	bio.close(f)
 }
--- a/bench/many-memcpy.myr
+++ b/bench/many-memcpy.myr
@@ -1,27 +1,31 @@
 use std
+use testr
 
+var a : uint64[100000]
+
 const main = {
-	var a : uint64[100000]
+	testr.bench([
+		[.name="fwd-independent", .fn=fwd_independent],
+		[.name="rev-independent", .fn=rev_independent],
+		[.name="fwd-dependent", .fn=fwd_dependent],
+		[.name="rev-dependent", .fn=rev_dependent],
+	][:])
+}
 
-	for var j = 0; j < 100; j++
-		/* independent copies forward */
-		for var i = 0; i < 10; i++
-			std.slcp(a[:a.len/2-1], a[a.len/2+1:])
-		;;
-		/* independent copies backward */
-		for var i = 0; i < 10; i++
-			std.slcp(a[:a.len/2-1], a[a.len/2+1:])
-		;;
+const fwd_independent = {ctx
+	std.slcp(a[:a.len/2-1], a[a.len/2+1:])
+}
 
-		/* dependent copies forward */
-		for var i = 0; i < 10; i++
-			std.slcp(a[:a.len/2+1000], a[a.len/2-1000:])
-		;;
-		/* dependent copies backward */
-		for var i = 0; i < 10; i++
-			std.slcp(a[a.len/2-1000:], a[:a.len/2+1000])
-		;;
-	;;
+const rev_independent = {ctx
+	std.slcp(a[:a.len/2-1], a[a.len/2+1:])
+}
+
+const fwd_dependent = {ctx
+	std.slcp(a[:a.len/2+1000], a[a.len/2-1000:])
+}
+
+const rev_dependent = {ctx
+	std.slcp(a[a.len/2-1000:], a[:a.len/2+1000])
 }
 
 
--- a/bench/regex-match.myr
+++ b/bench/regex-match.myr
@@ -1,26 +1,36 @@
 use std
 use regex
+use testr
 
-const main = {
-	var str, re, i
+var str
+var dotstar, hello
 
-	str = "€i²æ&±-ŝ€i²æ&±-ŝ€i²æ&±-ŝ€i²æ&±-ŝ€i²æ&±-ŝüüü€i²æ&±-ŝüüü€i²æ&±-ŝü"
+const main = {
+	str = std.sldup("hello world!")
 	str = std.strcat(str, str)
 	str = std.strcat(str, str)
 	str = std.strcat(str, str)
 	str = std.strcat(str, str)
 
-	for i = 0; i < 100; i++
-		match regex.compile(".*")
-		| `std.Ok r:	re = r
-		| `std.Err m:	std.fatal("couldn't compile regex: %s\n", m)
-		;;
+	dotstar = std.try(regex.compile(".*"))
+	hello = std.try(regex.compile("hel*o"))
 
-		match regex.exec(re, str)
-		| `std.Some m:
-		| `std.None:	std.fatal("Didn't match regex\n")
-		;;
+	testr.bench([
+		[.name="matchall", .fn=matchall],
+		[.name="searchhello", .fn=searchhello],
+	][:])
+}
 
-		regex.free(re)
+const matchall = {ctx
+	match regex.exec(dotstar, str)
+	| `std.Some m:	regex.matchfree(m)
+	| `std.None:	std.fatal("Didn't match regex\n")
+	;;
+}
+
+const searchhello = {ctx
+	match regex.search(dotstar, str)
+	| `std.Some m:	regex.matchfree(m)
+	| `std.None:	std.fatal("Didn't match regex\n")
 	;;
 }
--- a/bench/runbench.myr
+++ /dev/null
@@ -1,59 +1,0 @@
-use std
-
-const Nsamp = 10
-
-const main = {args : byte[:][:]
-	var tot : flt64
-
-	std.put("Running benchmarks: {} samples per binary\n", Nsamp);
-	tot = 0.0;
-	for arg : args[1:]
-		tot = tot + timeit(arg)
-	;;
-	std.put("total:\t{}s\n", tot);
-}
-
-const timeit = {prog -> flt64
-	var avg, m, d, x, n : flt64
-
-	avg = 0.0;
-	m = 0.0;
-	n = 0.0;
-	for var i = 0; i < Nsamp; i++
-		n = n + 1.0;
-		x = run(prog);
-		d = (x - avg);
-		avg = avg + d/n;
-		m = m + d*(x - avg);
-	;;
-	std.put("{}:\t{}s (σ^2: {})\n", prog, avg, m/(n-1.0));
-	-> avg;
-}
-
-const run = {prog -> flt64
-	var infd, outfd
-	var pid
-	var tm
-
-	tm = std.now()
-	pid = std.fork();
-	if pid < 0
-		std.fatal("Could not fork\n");
-	elif pid == 0
-		infd = std.try(std.open("/dev/zero", std.Ordonly))
-		outfd = std.try(std.open("/dev/null", std.Owronly))
-		std.try(std.dup2(infd, 0))
-		std.try(std.dup2(outfd, 1))
-		std.execv(prog, [prog][:])
-		std.fatal("Failed to exec\n")
-	else
-		match std.wait(pid)
-		| `std.Wfailure:	std.fatal("could not wait\n")
-		| `std.Waiterror:	std.fatal("running benchmark failed\n")
-		| `std.Wsignalled:	std.fatal("running benchmark failed\n")
-		| `std.Wsuccess:	/* nothing */
-		;;
-	;;
-	-> (std.now() - tm : flt64) / 1_000_000.0
-}
-
--- a/bench/sha1-compute.myr
+++ b/bench/sha1-compute.myr
@@ -1,20 +1,26 @@
 use crypto
 use std
+use testr
 
-const N = 20
+var buf : byte[128*1024*1024]
+
 const main = {
-	var i, b
-	var buf : byte[1024*1024]
+	for var i = 0; i < buf.len; i++
+		buf[i] = (i : byte)
+	;;
+	testr.bench([
+		[.name="sha1-1kb", .fn={ctx; hash(std.KiB)}],
+		[.name="sha1-1mb", .fn={ctx; hash(std.MiB)}],
+		[.name="sha1-16mb", .fn={ctx; hash(16*std.MiB)}],
+		[.name="sha1-128mb", .fn={ctx; hash(128*std.MiB)}],
+	][:])
+}
+
+const hash = {len
 	var st
 
-	b = 0
-	for i = 0; i < buf.len; i++
-		buf[i] = b++
-	;;
-	for i = 0; i < N; i++
-		crypto.sha1init(&st)
-		crypto.sha1add(&st, buf[:])
-		crypto.sha1fin(&st)
-	;;
+	crypto.sha1init(&st)
+	crypto.sha1add(&st, buf[:len])
+	crypto.sha1fin(&st)
 }
 
--- a/lib/regex/interp.myr
+++ b/lib/regex/interp.myr
@@ -164,7 +164,10 @@
 		next = thr.next
 		thrfree(re, thr)
 	;;
+	re.runq = Zthr
+	re.expired = Zthr
 	re.nexttid = 0
+	re.nthr = 0
 }
 
 const matchfree = {m
--- a/lib/std/bytealloc.myr
+++ b/lib/std/bytealloc.myr
@@ -125,6 +125,7 @@
 const bytealloc = {sz
 	var bkt, p
 
+	sz += 8
 	if sz <= Bktmax
 		bkt = &buckets[bktnum(sz)]
 		lock(memlck)
@@ -144,7 +145,12 @@
 /* frees a blob that is 'sz' bytes long. */
 const bytefree = {p, sz
 	var bkt
+	var v
 
+	if p == (0 : byte#)
+		-> void
+	;;
+	v = ((p : size) + sz : uint32#)#
 	if trace
 		lock(memlck)
 		tracefree(p, sz)
@@ -256,6 +262,7 @@
 		bkt.cache = s.next
 		bkt.ncache--
 	;;
+
 	/*
 	tricky: we need power of two alignment, so we allocate double the
 	needed size, chop off the unaligned ends, and waste the address
@@ -310,13 +317,12 @@
 	b = s.freehd
 	s.freehd = b.next
 	s.nfree--
-	if s.nfree == 0
+	if s.freehd == Zchunk
 		bkt.slabs = s.next
 		if s.next != Zslab
 			s.next.prev = Zslab
 		;;
 	;;
-
 	-> (b : byte#)
 }
 
@@ -343,21 +349,21 @@
 		HACK HACK HACK: if we can't unmap, keep an infinite cache per slab size.
 		We should solve this better somehow.
 		*/
+		/* unlink the slab from the list */
+		if s.next != Zslab
+			s.next.prev = s.prev
+		;;
+		if s.prev != Zslab
+			s.prev.next = s.next
+		;;
+		if bkt.slabs == s
+			bkt.slabs = s.next
+		;;
 		if bkt.ncache < Cachemax || !Canunmap
 			s.next = bkt.cache
 			s.prev = Zslab
 			bkt.cache = s
 		else
-			/* unlink the slab from the list */
-			if s.next != Zslab
-				s.next.prev = s.prev
-			;;
-			if s.prev != Zslab
-				s.prev.next = s.next
-			;;
-			if bkt.slabs == s
-				bkt.slabs = s.next
-			;;
 			/* we mapped 2*Slabsz so we could align it,
 			 so we need to unmap the same */
 			freemem(s.head, Slabsz*2)
@@ -435,3 +441,4 @@
 const mtrunc = {m, align
 	-> ((m : intptr) & ~((align : intptr) - 1) : byte#)
 }
+
--- a/mbld/test.myr
+++ b/mbld/test.myr
@@ -14,14 +14,14 @@
 ;;
 
 const test = {b, targs
-	-> go(b, targs, "test")
+	-> go(b, targs, "test", false)
 }
 
 const bench = {b, targs
-	-> go(b, targs, "bench")
+	-> go(b, targs, "bench", true)
 }
 
-const go = {b, targs, kind
+const go = {b, targs, kind, isbench
 	var failed, ok
 	var tests
 
@@ -42,7 +42,7 @@
 	ok = true
 	failed = [][:]
 	for t : tests
-		if !runtest(b, t, &failed)
+		if !runtest(b, t, isbench, &failed)
 			ok = false
 		;;
 	;;
@@ -71,7 +71,7 @@
 	;;
 }
 
-const runtest = {b, n, failed
+const runtest = {b, n, isbench, failed
 	var dir, res, log, logfd
 	var sub
 
@@ -100,7 +100,13 @@
 			/* if we have subtests, we've already printed the output */
 			match sub
 			| `std.Some r:	res = r
-			| `std.None:	mbldput("PASS\n")
+			| `std.None:
+				if isbench
+					mbldput("MISSING TIMING\n")
+					res = false
+				else
+					mbldput("PASS\n")
+				;;
 			;;
 		;;
 		if !res