From d0ed08c4a395c9ede3883a470275821cdee75a53 Mon Sep 17 00:00:00 2001 From: Jaremy Creechley Date: Wed, 1 Nov 2023 17:05:55 -0700 Subject: [PATCH] non-procs --- chronos/futures.nim | 8 +- tests/config.nims | 2 +- tests/testutils.nim | 180 ++++++++++++++++++++++---------------------- 3 files changed, 97 insertions(+), 93 deletions(-) diff --git a/chronos/futures.nim b/chronos/futures.nim index 92a4929..e67433a 100644 --- a/chronos/futures.nim +++ b/chronos/futures.nim @@ -95,10 +95,10 @@ when chronosFutureTracking: when chronosFuturesInstrumentation: var - onFutureCreate* {.threadvar.}: proc (fut: FutureBase) {.gcsafe, raises: [].} - onFutureRunning* {.threadvar.}: proc (fut: FutureBase) {.gcsafe, raises: [].} - onFuturePause* {.threadvar.}: proc (fut, child: FutureBase) {.gcsafe, raises: [].} - onFutureStop* {.threadvar.}: proc (fut: FutureBase) {.gcsafe, raises: [].} + onFutureCreate*: proc (fut: FutureBase) {.gcsafe, nimcall, raises: [].} + onFutureRunning*: proc (fut: FutureBase) {.gcsafe, nimcall, raises: [].} + onFuturePause*: proc (fut, child: FutureBase) {.gcsafe, nimcall, raises: [].} + onFutureStop*: proc (fut: FutureBase) {.gcsafe, nimcall, raises: [].} # Internal utilities - these are not part of the stable API proc internalInitFutureBase*( diff --git a/tests/config.nims b/tests/config.nims index 9a3d66f..00648b8 100644 --- a/tests/config.nims +++ b/tests/config.nims @@ -9,5 +9,5 @@ switch("threads", "on") switch("define", "nimRawSetjmp") ## REMOVE BEFORE MERGE! ---d:chronosFuturesInstrumentation +# --d:chronosFuturesInstrumentation # --d:chronosFutureTracking diff --git a/tests/testutils.nim b/tests/testutils.nim index 4ce5b52..c6045f2 100644 --- a/tests/testutils.nim +++ b/tests/testutils.nim @@ -14,6 +14,29 @@ when chronosFuturesInstrumentation: import std/[tables, os, options, hashes] import ../chronos/timer +type + FutureMetric = object + ## Holds average timing information for a given closure + closureLoc*: ptr SrcLoc + created*: Moment + start*: Option[Moment] + duration*: Duration + blocks*: int + initDuration*: Duration + durationChildren*: Duration + + CallbackMetric = object + totalExecTime*: Duration + totalWallTime*: Duration + totalRunTime*: Duration + minSingleTime*: Duration + maxSingleTime*: Duration + count*: int64 + +var + futureDurations: Table[uint, FutureMetric] + callbackDurations: Table[ptr SrcLoc, CallbackMetric] + suite "Asynchronous utilities test suite": when chronosFutureTracking: proc getCount(): uint = @@ -113,109 +136,90 @@ suite "Asynchronous utilities test suite": when chronosFuturesInstrumentation: - type - FutureMetric = object - ## Holds average timing information for a given closure - closureLoc*: ptr SrcLoc - created*: Moment - start*: Option[Moment] - duration*: Duration - blocks*: int - initDuration*: Duration - durationChildren*: Duration - - CallbackMetric = object - totalExecTime*: Duration - totalWallTime*: Duration - totalRunTime*: Duration - minSingleTime*: Duration - maxSingleTime*: Duration - count*: int64 - - var - futureDurations: Table[uint, FutureMetric] - callbackDurations: Table[ptr SrcLoc, CallbackMetric] - - proc setFutureCreate(fut: FutureBase) {.raises: [].} = + proc setFutureCreate(fut: FutureBase) {.nimcall, gcsafe, raises: [].} = ## used for setting the duration - let loc = fut.internalLocation[Create] - futureDurations[fut.id] = FutureMetric() - futureDurations.withValue(fut.id, metric): - metric.created = Moment.now() - echo loc, "; future create " + {.cast(gcsafe).}: + let loc = fut.internalLocation[Create] + futureDurations[fut.id] = FutureMetric() + futureDurations.withValue(fut.id, metric): + metric.created = Moment.now() + echo loc, "; future create " - proc setFutureStart(fut: FutureBase) {.raises: [].} = + proc setFutureStart(fut: FutureBase) {.nimcall, gcsafe, raises: [].} = ## used for setting the duration - let loc = fut.internalLocation[Create] - assert futureDurations.hasKey(fut.id) - futureDurations.withValue(fut.id, metric): - let ts = Moment.now() - metric.start = some ts - metric.blocks.inc() - echo loc, "; future start: ", metric.initDuration - - proc setFuturePause(fut, child: FutureBase) {.raises: [].} = - ## used for setting the duration - let loc = fut.internalLocation[Create] - let childLoc = if child.isNil: nil else: child.internalLocation[Create] - var durationChildren = ZeroDuration - var initDurationChildren = ZeroDuration - if childLoc != nil: - futureDurations.withValue(child.id, metric): - durationChildren = metric.duration - initDurationChildren = metric.initDuration - assert futureDurations.hasKey(fut.id) - futureDurations.withValue(fut.id, metric): - if metric.start.isSome: + {.cast(gcsafe).}: + let loc = fut.internalLocation[Create] + assert futureDurations.hasKey(fut.id) + futureDurations.withValue(fut.id, metric): let ts = Moment.now() - metric.duration += ts - metric.start.get() - metric.duration -= initDurationChildren - if metric.blocks == 1: - metric.initDuration = ts - metric.created # tricky, - # the first block of a child iterator also - # runs on the parents clock, so we track our first block - # time so any parents can get it - echo loc, "; child firstBlock time: ", initDurationChildren + metric.start = some ts + metric.blocks.inc() + echo loc, "; future start: ", metric.initDuration - metric.durationChildren += durationChildren - metric.start = none Moment - echo loc, "; future pause ", if childLoc.isNil: "" else: " child: " & $childLoc - - proc setFutureDuration(fut: FutureBase) {.raises: [].} = + proc setFuturePause(fut, child: FutureBase) {.nimcall, gcsafe, raises: [].} = ## used for setting the duration - let loc = fut.internalLocation[Create] - # assert "set duration: " & $loc - var fm: FutureMetric - # assert futureDurations.pop(fut.id, fm) - futureDurations.withValue(fut.id, metric): - fm = metric[] + {.cast(gcsafe).}: + let loc = fut.internalLocation[Create] + let childLoc = if child.isNil: nil else: child.internalLocation[Create] + var durationChildren = ZeroDuration + var initDurationChildren = ZeroDuration + if childLoc != nil: + futureDurations.withValue(child.id, metric): + durationChildren = metric.duration + initDurationChildren = metric.initDuration + assert futureDurations.hasKey(fut.id) + futureDurations.withValue(fut.id, metric): + if metric.start.isSome: + let ts = Moment.now() + metric.duration += ts - metric.start.get() + metric.duration -= initDurationChildren + if metric.blocks == 1: + metric.initDuration = ts - metric.created # tricky, + # the first block of a child iterator also + # runs on the parents clock, so we track our first block + # time so any parents can get it + echo loc, "; child firstBlock time: ", initDurationChildren - discard callbackDurations.hasKeyOrPut(loc, CallbackMetric(minSingleTime: InfiniteDuration)) - callbackDurations.withValue(loc, metric): - echo loc, " set duration: ", callbackDurations.hasKey(loc) - metric.totalExecTime += fm.duration - metric.totalWallTime += Moment.now() - fm.created - metric.totalRunTime += metric.totalExecTime + fm.durationChildren - echo loc, " child duration: ", fm.durationChildren - metric.count.inc - metric.minSingleTime = min(metric.minSingleTime, fm.duration) - metric.maxSingleTime = max(metric.maxSingleTime, fm.duration) - # handle overflow - if metric.count == metric.count.typeof.high: - metric.totalExecTime = ZeroDuration - metric.count = 0 + metric.durationChildren += durationChildren + metric.start = none Moment + echo loc, "; future pause ", if childLoc.isNil: "" else: " child: " & $childLoc + + proc setFutureDuration(fut: FutureBase) {.nimcall, gcsafe, raises: [].} = + ## used for setting the duration + {.cast(gcsafe).}: + let loc = fut.internalLocation[Create] + # assert "set duration: " & $loc + var fm: FutureMetric + # assert futureDurations.pop(fut.id, fm) + futureDurations.withValue(fut.id, metric): + fm = metric[] + + discard callbackDurations.hasKeyOrPut(loc, CallbackMetric(minSingleTime: InfiniteDuration)) + callbackDurations.withValue(loc, metric): + echo loc, " set duration: ", callbackDurations.hasKey(loc) + metric.totalExecTime += fm.duration + metric.totalWallTime += Moment.now() - fm.created + metric.totalRunTime += metric.totalExecTime + fm.durationChildren + echo loc, " child duration: ", fm.durationChildren + metric.count.inc + metric.minSingleTime = min(metric.minSingleTime, fm.duration) + metric.maxSingleTime = max(metric.maxSingleTime, fm.duration) + # handle overflow + if metric.count == metric.count.typeof.high: + metric.totalExecTime = ZeroDuration + metric.count = 0 onFutureCreate = - proc (f: FutureBase) = + proc (f: FutureBase) {.nimcall, gcsafe, raises: [].} = f.setFutureCreate() onFutureRunning = - proc (f: FutureBase) = + proc (f: FutureBase) {.nimcall, gcsafe, raises: [].} = f.setFutureStart() onFuturePause = - proc (f, child: FutureBase) = + proc (f, child: FutureBase) {.nimcall, gcsafe, raises: [].} = f.setFuturePause(child) onFutureStop = - proc (f: FutureBase) = + proc (f: FutureBase) {.nimcall, gcsafe, raises: [].} = f.setFuturePause(nil) f.setFutureDuration()