use cligen for benchmarking

This commit is contained in:
Joseph Montanaro 2021-07-20 16:16:01 -07:00
parent e5e90a6ca5
commit 7301597789

102
test.nim
View File

@ -1,13 +1,18 @@
import math, random, strformat, strutils, times, std/monotimes import math, random, strformat, strutils, times, std/monotimes
import cligen
import fixedseq, game, simulation import fixedseq, game, simulation
type type
TestResults = object TestResults = object
ops: int scores: ScoreSet
time: Duration time: Duration
proc ops(tr: TestResults): int =
result = sum(tr.scores)
proc formatNum(n: SomeNumber, decimals = 0): string = proc formatNum(n: SomeNumber, decimals = 0): string =
when n is SomeFloat: when n is SomeFloat:
let s = $n.round(decimals) let s = $n.round(decimals)
@ -22,70 +27,79 @@ proc formatNum(n: SomeNumber, decimals = 0): string =
proc summarize(tr: TestResults, opname = "operations") = proc summarize(tr: TestResults, opname = "operations") =
let secs = tr.time.inMilliseconds.float / 1000 let secs = tr.time.inMilliseconds.float / 1000
stdout.write("Test completed:\n") stdout.write("Test completed:\n")
stdout.write(&" {tr.ops.formatNum} {opname} in {secs.formatNum} seconds\n") stdout.write(&" {tr.ops.formatNum} {opname} in {secs.formatNum(2)} seconds\n")
stdout.write(&" {(tr.ops.float / secs).formatNum} {opname} per second") stdout.write(&" {(tr.ops.float / secs).formatNum} {opname} per second\n")
stdout.flushFile() stdout.flushFile()
# proc getRand(): Rand =
# randomize()
# result = initRand(rand(int64))
proc newRandomGame(): Board =
randomize()
var dice: array[5, tuple[c: Color, p: int]]
for i in 0 .. 4:
dice[i] = (Color(i), rand(1..3))
result.init
result.setState(dice, [])
template executionTime(body: untyped): Duration = template executionTime(body: untyped): Duration =
let start = getMonoTime() let start = getMonoTime()
body body
getMonoTime() - start getMonoTime() - start
proc getRand(): Rand = # template runTest(loops: Natural, opname = "operations", body: ScoreSet): TestResults =
randomize() # var res: TestResults
result = initRand(rand(int64)) # for i in 1 .. loops:
# let start = getMonoTime()
# let s = body
# res.time += (getMonoTime() - start)
# res.scores.update(s)
# res.summarize(opname)
proc randomDice(r: var Rand): seq[tuple[c: Color, p: int]] = # proc games(runs, samples: Natural, parallel = true) =
for c in Color: # let b = newRandomGame()
let v = r.rand(1..3) # runTest(runs, "games"):
result.add((c, v)) # b.randomGames(samples, parallel = parallel)
result.shuffle
proc newRandomGame(r: var Rand): Board = # proc legs(runs: Natural) =
var dice: array[5, tuple[c: Color, p: int]] # let b = newRandomGame()
for i in 0 .. 4: # runTest(runs, "legs"):
dice[i] = (Color(i), r.rand(1..3)) # b.getLegScores
result.init
result.setState(dice, [])
proc games(nTests, nSamples: Natural, parallel = true) = proc games(runs, samples: Natural, parallel = true) =
var r = getRand()
var scores: ScoreSet
var res: TestResults var res: TestResults
for i in 1 .. nTests: for i in 1 .. runs:
let b = newRandomGame(r) let b = newRandomGame()
let dur = executionTime: let dur = executionTime:
let s = b.randomGames(nSamples, parallel = parallel) let s = b.randomGames(samples, parallel = parallel)
scores.update(s) res.scores.update(s)
res.ops += s.sum()
res.time += dur res.time += dur
res.summarize("games") res.summarize("games")
proc legs(nTests: Natural) = proc legs(runs: Natural) =
var r = getRand()
var scores: ScoreSet
var res: TestResults var res: TestResults
for i in 1 .. nTests: for i in 1 .. runs:
let b = newRandomGame(r) let b = newRandomGame()
let dur = executionTime: let dur = executionTime:
let s = b.getLegScores let s = b.getLegScores
scores.update(s) res.scores.update(s)
res.ops += s.sum
res.time += dur res.time += dur
res.summarize("legs") res.summarize("legs")
proc spread(nTests, nSamples: Natural) = proc spread(runs, samples: Natural) =
var r = getRand() let b = newRandomGame()
let b = newRandomGame(r) let spread = randomSpread(b, runs, samples)
let spread = randomSpread(b, nTests, nSamples)
stdout.writeLine("Variance:") stdout.writeLine("Variance:")
for c in Color: for c in Color:
@ -98,5 +112,17 @@ proc spread(nTests, nSamples: Natural) =
stdout.flushFile() stdout.flushFile()
const help_runs = "Number of times to run the test"
const help_samples = "Number of iterations per run"
const help_parallel = "Run test in parallel or single-threaded (default parallel)"
proc bench() =
dispatchMulti(
[games, help = {"runs": help_runs, "samples": help_samples, "parallel": help_parallel}],
[legs, help = {"runs": help_runs}],
[spread, help = {"runs": help_runs, "samples": help_samples}]
)
when isMainModule: when isMainModule:
legs(3000) bench()