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