2025-03-06 16:32:33 +01:00

89 lines
2.3 KiB
Nim

import std/tables
template withDir*(dir: string, blk: untyped) =
## set working dir for duration of blk
let prev = getCurrentDir()
try:
setCurrentDir(dir)
`blk`
finally:
setCurrentDir(prev)
template runit*(cmd: string) =
## run shell commands and verify it runs without an error code
echo "RUNNING: ", cmd
let cmdRes = execShellCmd(cmd)
echo "STATUS: ", cmdRes
assert cmdRes == 0
var benchRuns* = newTable[string, tuple[avgTimeSec: float, avgMem: int, count: int]]()
func avg(vals: openArray[float]): float =
for v in vals:
result += v / vals.len().toFloat()
func avg(vals: openArray[int]): int =
for v in vals:
result += v
result = result div vals.len()
template benchmark*(name: untyped, count: int, blk: untyped) =
let benchmarkName: string = name
## simple benchmarking of a block of code
var times = newSeqOfCap[float](count)
var mems = newSeqOfCap[int](count)
for i in 1 .. count:
block:
let m0 = getOccupiedMem()
let t0 = epochTime()
`blk`
let elapsed = epochTime() - t0
let mem = getOccupiedMem() - m0
times.add elapsed
mems.add mem
var elapsedStr = ""
var memStr = ""
for v in times:
elapsedStr &= ", " & v.formatFloat(format = ffDecimal, precision = 3)
for m in mems:
memStr &= ", " & $m & " bytes"
stdout.styledWriteLine(
fgGreen, "CPU Time [", benchmarkName, "] ", "avg(", $count, "): ", elapsedStr, " s ", memStr
)
benchRuns[benchmarkName] = (times.avg(), mems.avg(), count)
template printBenchMarkSummaries*(printRegular=true, printTsv=true) =
if printRegular:
echo ""
for k, v in benchRuns:
echo "Benchmark average run ", v.avgTimeSec, "s ", v.avgMem, "b for ", v.count, " runs ", "for ", k
if printTsv:
echo ""
echo "name", "\t", "avgTimeSec", "\t", "avgMem", "\t", "count"
for k, v in benchRuns:
echo k, "\t", v.avgTimeSec, "\t", v.avgMem, "\t", v.count
import std/math
func floorLog2*(x: int): int =
var k = -1
var y = x
while (y > 0):
k += 1
y = y shr 1
return k
func ceilingLog2*(x: int): int =
if (x == 0):
return -1
else:
return (floorLog2(x - 1) + 1)
func checkPowerOfTwo*(x: int, what: string): int =
let k = ceilingLog2(x)
assert(x == 2 ^ k, ("`" & what & "` is expected to be a power of 2"))
return x