ref: 1b1439cd64f73986909b85c99c91c2195d4ab58f
parent: 8441b63d07bc96852b3ac986adb6d816d1412954
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Sep 3 18:42:59 EDT 2017
Add support for printing mtest benchmarks.
--- a/lib/testr/testr.myr
+++ b/lib/testr/testr.myr
@@ -24,7 +24,7 @@
const Nsamp = 1000;
const bench = {specs
- std.put("MBENCH {}\n", specs.len)
+ std.put("MTEST {}\n", specs.len)
for s : specs
benchspec(&s)
;;
@@ -70,8 +70,11 @@
}
const softfailv = {ctx, msg, ap
- ctx.ok = false
- ctx.reason = std.fmtv(msg, ap)
+ /* keep the first failure */
+ if ctx.ok
+ ctx.ok = false
+ ctx.reason = std.fmtv(msg, ap)
+ ;;
}
const benchspec = {ts
@@ -87,7 +90,7 @@
avg = 0.0;
m = 0.0;
n = 0.0;
- std.put("bench {} <<{{!\n", ts.name)
+ std.put("test {} <<{{!\n", ts.name)
if !std.setjmp(&jmpbuf)
for var i = 0; i < Nsamp; i++
n +=1.0;
@@ -101,7 +104,7 @@
;;
if ctx.ok
- std.put("!}}>> timings {} {} {}\n", Nsamp, avg, m)
+ std.put("!}}>> timing {} {} {}\n", Nsamp, avg, m)
else
std.put("!}}>> fail {}\n", ctx.reason)
std.slfree(ctx.reason)
--- a/mbld/subtest.myr
+++ b/mbld/subtest.myr
@@ -18,7 +18,7 @@
const __init__ = {
planpat = std.try(regex.compile("MTEST\\s+(-?\\d+)\\s*"))
headpat = std.try(regex.compile("test\\s+(.*)<<{!\\s*"))
- footpat = std.try(regex.compile("!}>>\\s*(ok|fail\\s*(.*))\\s*"))
+ footpat = std.try(regex.compile("!}>>\\s*(ok|fail|timing)\\s*(.*)\\s*"))
}
const showsub = {b, cmd, fd, logfd, failed
@@ -75,7 +75,7 @@
curtest = ""
nresults = 0
mbldput("\n")
- for ln in bio.byline(f)
+ for ln : bio.byline(f)
ln = std.strstrip(ln)
match testhead(ln)
| `std.None:
@@ -87,11 +87,14 @@
match testfoot(ln)
| `std.None:
- | `std.Some `std.Ok _:
- endtest(b, cmd, &curtest, failed, &nresults, true, "")
+ | `std.Some `Timing (niter, avg, stddev):
+ showbench(b, &curtest, &nresults, niter, avg, stddev)
continue
- | `std.Some `std.Err m:
- endtest(b, cmd, &curtest, failed, &nresults, false, m)
+ | `std.Some `Pass:
+ passtest(b, &curtest, &nresults)
+ continue
+ | `std.Some `Fail m:
+ failtest(b, cmd, &curtest, failed, &nresults, m)
ok = false
continue
;;
@@ -133,25 +136,50 @@
curtest# = t
}
-const endtest = {b, cmd, curtest, failed, nresults, pass, msg
- var p
+const passtest = {b, curtest, nresults
+ donetest(b, curtest, nresults)
+ mbldput("PASS\n")
+}
- if curtest#.len == 0
- std.fatal("malformed input: test ended without start\n")
- ;;
+const showbench = {b, curtest, nresults, niter, avg, stddev
+ var scale, unit
+ donetest(b, curtest, nresults)
+ (scale, unit) = displayscale(avg)
+ std.put("BENCH:\t{}{} (σ^2: {})\n", avg*scale, unit, stddev*scale);
+}
- if pass
- mbldput("PASS\n")
- else
- if msg.len > 0
- mbldput("FAIL {}\n", msg)
- else
- mbldput("FAIL\n")
+const units = [
+ "s",
+ "ms",
+ "μs",
+ "ns",
+]
+const displayscale = {val
+ var scale
+
+ scale = 1.0
+ for var i = 0; i < units.len; i++
+ if val*scale > 1.0
+ -> (scale, units[i])
;;
- p = std.pathcat(cmd, curtest#)
- std.slpush(failed, p)
+ scale *= 1000.0
;;
+ -> (scale, units[units.len - 1])
+}
+const failtest = {b, cmd, curtest, failed, nresults, msg
+ var p
+
+ p = std.pathcat(cmd, curtest#)
+ donetest(b, curtest, nresults)
+ mbldput("FAIL {}\n", msg)
+ std.slpush(failed, p)
+}
+
+const donetest = {b, curtest, nresults
+ if curtest#.len == 0
+ std.fatal("malformed input: test ended without start\n")
+ ;;
std.slfree(curtest#)
curtest# = ""
nresults#++
@@ -183,16 +211,44 @@
;;
}
-const testfoot : (ln : byte[:] -> std.option(std.result(void, byte[:]))) = {ln
+const testfoot = {ln
match regex.exec(footpat, ln)
| `std.Some m:
- if std.sleq(m[1], "ok")
- -> `std.Some `std.Ok void
- else
- -> `std.Some `std.Err std.sldup(m[2])
+ match m[1]
+ | "timing": -> parsetiming(m[2])
+ | "ok": -> `std.Some `Pass
+ | "fail": -> `std.Some `Fail std.sldup(m[2])
+ | junk: -> `std.Some `Fail std.fmt("garbled : {}", junk)
;;
| `std.None:
-> `std.None
;;
+}
+
+const parsetiming = {tm
+ var niter, avg, stddev
+ var sp, buf : byte[:][3]
+
+ sp = std.bstrtok(buf[:], tm)
+ if sp.len != 3
+ -> `std.None
+ ;;
+
+ match std.intparse(sp[0])
+ | `std.Some n: niter = n
+ | `std.None: -> `std.None
+ ;;
+
+ match std.flt64parse(sp[1])
+ | `std.Some n: avg = n
+ | `std.None: -> `std.None
+ ;;
+
+ match std.flt64parse(sp[2])
+ | `std.Some n: stddev = n
+ | `std.None: -> `std.None
+ ;;
+
+ -> `std.Some `Timing (niter, avg, stddev)
}
--- a/mbld/types.myr
+++ b/mbld/types.myr
@@ -82,6 +82,12 @@
genar : byte[:]
;;
+ type testresult = union
+ `Pass
+ `Fail byte[:]
+ `Timing (int, flt64, flt64)
+ ;;
+
type depgraph = struct
/* the edges of the graph from both ends */
targs : std.htab(byte[:], node#[:])#