...
 
Commits (6)
......@@ -24,12 +24,14 @@ proc secs*(nsecs: int64): float {.inline.}
type
Stopwatch* = object
running: bool
startTicks: Ticks
startTicks: Ticks
recordLaps: bool
previousLap: Ticks
laps: seq[Ticks]
total: Nanos
# Basic stopwatch functionality
proc stopwatch*(): Stopwatch
proc stopwatch*(enableLapping:bool = true): Stopwatch
proc clone*(sw: var Stopwatch): Stopwatch
proc running*(sw: var Stopwatch): bool {.inline.}
proc start*(sw: var Stopwatch) {.inline.}
......@@ -38,6 +40,7 @@ proc reset*(sw: var Stopwatch) {.inline.}
proc restart*(sw: var Stopwatch) {.inline.}
# Lap functions
proc isRecordingLaps*(sw: var Stopwatch;): bool {.inline.}
proc numLaps*(sw: var Stopwatch; incCur: bool = false): int {.inline.}
proc lap*(sw: var Stopwatch; num: int; incCur: bool = false): int64 {.inline.}
proc laps*(sw: var Stopwatch; incCur: bool = false): seq[int64] {.inline.}
......@@ -123,12 +126,16 @@ proc secs*(nsecs: int64): float =
#== Stopwatch procs ==#
#=====================#
## Creates a new Stopwatch. It has no laps and isn't running
proc stopwatch*(): Stopwatch =
## Creates a new Stopwatch. It has no laps and isn't running. If you want to
## turn of lapping then pass `false` to the `enableLapping` paramater. By
## default it is on.
proc stopwatch*(enableLapping:bool): Stopwatch =
result = Stopwatch(
running: false,
startTicks: 0.Ticks,
laps: @[],
recordLaps: enableLapping,
previousLap: 0.Ticks,
laps: if enableLapping: @[] else: nil,
total: 0
)
......@@ -139,6 +146,8 @@ proc clone*(sw: var Stopwatch): Stopwatch =
result = Stopwatch(
running: sw.running,
startTicks: sw.startTicks,
recordLaps: sw.recordLaps,
previousLap: sw.previousLap,
laps: sw.laps,
total: sw.total
)
......@@ -171,9 +180,15 @@ proc stop*(sw: var Stopwatch) =
if not sw.running:
return
# save the lap that we just made (and add it to the accum)
# Get lap time
let lapTime = stopTicks - sw.startTicks
sw.laps.add(lapTime.Ticks)
# Save it to the laps
if sw.isRecordingLaps:
sw.laps.add(lapTime.Ticks)
sw.previousLap = lapTime.Ticks
# Add it to the accum
sw.total += lapTime
# Reset timer state
......@@ -181,14 +196,18 @@ proc stop*(sw: var Stopwatch) =
sw.startTicks = 0.Ticks
## Clears out the state of the Stopwatch. This deletes all of the lap data and
## will make it stop measuring time.
## Clears out the state of the Stopwatch. This deletes all of the lap data (if
## lapping is enabled) and will stop the stopwatch.
proc reset*(sw: var Stopwatch) =
sw.running = false
sw.startTicks = 0.Ticks
sw.laps.setLen(0) # Clear the laps
sw.previousLap = 0.Ticks
sw.total = 0 # Zero the accum
# Clear the laps
if sw.isRecordingLaps:
sw.laps.setLen(0)
## This function will clear out the state of the Stopwatch and tell it to start
## recording time. It is the same as calling reset() then start().
......@@ -197,11 +216,21 @@ proc restart*(sw: var Stopwatch) =
sw.start()
## Checks to see if a stopwatch it recording laps or not. Returns true if so,
## false otherwise
proc isRecordingLaps*(sw: var Stopwatch;): bool =
return sw.recordLaps
## Returns the number of laps the Stopwatch has recorded so far. If `incCur` is
## set to `true`, it will include the current lap in the count. By default it
## set to `false`.
##
## If lapping is not enabled, this will 0
proc numLaps*(sw: var Stopwatch; incCur: bool = false): int =
return sw.laps.len + (if incCur and sw.running: 1 else: 0)
if sw.isRecordingLaps:
return sw.laps.len + (if incCur and sw.running: 1 else: 0)
else:
return 0
## Returns the time (in nanoseconds) of a lap with the provided index of `num`.
......@@ -211,12 +240,19 @@ proc numLaps*(sw: var Stopwatch; incCur: bool = false): int =
##
## If you want to convert the returned value to a different time measurement,
## use one of the functions: `msecs()`, `usecs()` or `secs()`.
##
## If lapping is not enabled then this will return 0
proc lap*(sw: var Stopwatch; num: int; incCur: bool = false): int64 =
# Check for not lapping
if not sw.isRecordingLaps:
return 0
# Else we've got laps
if incCur and sw.running:
# Check if the index is good or not
if num < sw.laps.len:
# Return one of the previous laps
return sw.laps[num].int64
# Return the previous lap
return sw.previousLap.int64
elif num == sw.laps.len:
# Return the current lap
return sw.nsecs
......@@ -244,7 +280,14 @@ proc lap*(sw: var Stopwatch; num: int; incCur: bool = false): int64 =
## var lapsSecs = sw2.laps.map(proc(x: int64): float = secs(x))
## echo lapsSecs
## # --> @[1.000117, 0.500115, 0.200212]
##
## If lapping is turned off this will return an empty sequence
proc laps*(sw: var Stopwatch; incCur: bool = false): seq[int64] =
# Check for lapping=off
if not sw.isRecordingLaps:
return @[]
# Nope, we've got laps
var
curLap = sw.nsecs
allLaps = cast[seq[int64]](sw.laps)
......@@ -256,8 +299,14 @@ proc laps*(sw: var Stopwatch; incCur: bool = false): seq[int64] =
## Removes a lap from the Stopwatch's record with the given index of `num`.
## This function has the possibility of raising an `IndexError`.
## This function has the possibility of raising an `IndexError`.
##
## If lapping is disabled, this function will do nothing.
proc rmLap*(sw: var Stopwatch; num: int) =
# Check for no laps
if not sw.isRecordingLaps:
return
# Remove its time from the accum
let t = sw.laps[num]
sw.total = sw.total.Ticks - t
......@@ -267,15 +316,24 @@ proc rmLap*(sw: var Stopwatch; num: int) =
## This clears out all of the lap records from a Stopwatch. This will not
## effect the current lap (if one is being measured).
##
## If lapping is disabled nothing will happen.
proc clearLaps(sw: var Stopwatch) =
# Check for no laps
if not sw.isRecordingLaps:
return
sw.laps.setLen(0)
sw.total = 0
sw.previousLap = 0.Ticks
## This will return either the length of the current lap (if `stop()` has not
## been called, or the time of the previously measured lap. The return value is
## in nanoseconds. If no laps have been run yet, then this will return 0.
##
## If lapping is turned off then this will act the same as `totalNsecs()`
##
## See also: `usecs()`, `msecs()`, `secs()`
proc nsecs*(sw: var Stopwatch): int64 =
let curTicks = getTicks_internal()
......@@ -283,9 +341,12 @@ proc nsecs*(sw: var Stopwatch): int64 =
if sw.running:
# Return current lap
return (curTicks - sw.startTicks).int64
elif not sw.isRecordingLaps:
# Lapping is off
return sw.previousLap.int64
elif sw.laps.len != 0:
# Return previous lap
return sw.laps[high(sw.laps)].int64
return sw.previousLap.int64
else:
# No laps yet
return 0
......
[Package]
name = "stopwatch"
version = "2.0"
version = "3.0"
author = "define-private-public"
description = "A simple timing library for benchmarking code and other things."
license = "MIT"
......
import stopwatch
import parseopt2
from os import sleep
from sequtils import map
var sw = stopwatch()
var
recordLaps = true
sw:Stopwatch
# Test with laps or no laps via an argument
for kind, key, val in getopt():
if (kind == cmdArgument) and (key == "nolap"):
recordLaps = false
# Print a message
echo "Testing with laps ", (if recordLaps: "on." else: "off.")
# Init the stopwatch and go
sw = stopwatch(recordLaps)
echo "laps=", sw.laps(true)
echo "total=", sw.totalSecs
......@@ -50,14 +67,14 @@ var sw2 = sw.clone()
echo "lapCount=", sw.numLaps
echo "L1=", sw.lap(0).secs
echo "L2=", sw.laps[1].secs
echo "L2=", if sw.isRecordingLaps: sw.laps()[1].secs else: 0
sw.rmLap(0)
echo "all laps=", sw.laps
echo "lapCount=", sw.numLaps
echo "----"
echo "lapCount=", sw2.numLaps
var lapsSecs = sw2.laps.map(proc(x: int64): float = secs(x))
var lapsSecs = sw2.laps().map(proc(x: int64): float = secs(x))
echo "all laps(s)=", lapsSecs
echo ""
......