From 7301597789dc2f2149c23a5fbf98c164e4306efa Mon Sep 17 00:00:00 2001 From: Joseph Montanaro Date: Tue, 20 Jul 2021 16:16:01 -0700 Subject: [PATCH] use cligen for benchmarking --- test.nim | 102 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/test.nim b/test.nim index 67798a8..1c48ef0 100644 --- a/test.nim +++ b/test.nim @@ -1,13 +1,18 @@ import math, random, strformat, strutils, times, std/monotimes +import cligen import fixedseq, game, simulation type TestResults = object - ops: int + scores: ScoreSet time: Duration +proc ops(tr: TestResults): int = + result = sum(tr.scores) + + proc formatNum(n: SomeNumber, decimals = 0): string = when n is SomeFloat: let s = $n.round(decimals) @@ -22,70 +27,79 @@ proc formatNum(n: SomeNumber, decimals = 0): string = proc summarize(tr: TestResults, opname = "operations") = let secs = tr.time.inMilliseconds.float / 1000 stdout.write("Test completed:\n") - stdout.write(&" {tr.ops.formatNum} {opname} in {secs.formatNum} seconds\n") - stdout.write(&" {(tr.ops.float / secs).formatNum} {opname} per second") + stdout.write(&" {tr.ops.formatNum} {opname} in {secs.formatNum(2)} seconds\n") + stdout.write(&" {(tr.ops.float / secs).formatNum} {opname} per second\n") 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 = let start = getMonoTime() body getMonoTime() - start -proc getRand(): Rand = - randomize() - result = initRand(rand(int64)) +# template runTest(loops: Natural, opname = "operations", body: ScoreSet): TestResults = +# var res: TestResults +# 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]] = - for c in Color: - let v = r.rand(1..3) - result.add((c, v)) - result.shuffle +# proc games(runs, samples: Natural, parallel = true) = +# let b = newRandomGame() +# runTest(runs, "games"): +# b.randomGames(samples, parallel = parallel) -proc newRandomGame(r: var Rand): Board = - var dice: array[5, tuple[c: Color, p: int]] - for i in 0 .. 4: - dice[i] = (Color(i), r.rand(1..3)) - - result.init - result.setState(dice, []) +# proc legs(runs: Natural) = +# let b = newRandomGame() +# runTest(runs, "legs"): +# b.getLegScores -proc games(nTests, nSamples: Natural, parallel = true) = - var r = getRand() - var scores: ScoreSet +proc games(runs, samples: Natural, parallel = true) = var res: TestResults - for i in 1 .. nTests: - let b = newRandomGame(r) + for i in 1 .. runs: + let b = newRandomGame() let dur = executionTime: - let s = b.randomGames(nSamples, parallel = parallel) - scores.update(s) - res.ops += s.sum() + let s = b.randomGames(samples, parallel = parallel) + res.scores.update(s) res.time += dur res.summarize("games") -proc legs(nTests: Natural) = - var r = getRand() - var scores: ScoreSet +proc legs(runs: Natural) = var res: TestResults - for i in 1 .. nTests: - let b = newRandomGame(r) + for i in 1 .. runs: + let b = newRandomGame() let dur = executionTime: let s = b.getLegScores - scores.update(s) - res.ops += s.sum + res.scores.update(s) res.time += dur res.summarize("legs") -proc spread(nTests, nSamples: Natural) = - var r = getRand() - let b = newRandomGame(r) - let spread = randomSpread(b, nTests, nSamples) +proc spread(runs, samples: Natural) = + let b = newRandomGame() + let spread = randomSpread(b, runs, samples) stdout.writeLine("Variance:") for c in Color: @@ -98,5 +112,17 @@ proc spread(nTests, nSamples: Natural) = 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: - legs(3000) + bench()