nim-chroprof/tests/utils.nim

67 lines
1.9 KiB
Nim

import chronos
import ../chroprof/[api, events, profiler]
type SimpleEvent* = object
procedure*: string
state*: ExtendedFutureState
# XXX this is sort of bad cause we get global state all over, but the fact we
# can't use closures on callbacks and that callbacks themselves are just
# global vars means we can't really do much better for now.
var recording*: seq[SimpleEvent]
var rawRecording*: seq[Event]
var fakeTime*: Moment = Moment.init(0, 1.milliseconds)
proc recordEvent(event: Event) {.nimcall, gcsafe, raises: [].} =
{.cast(gcsafe).}:
recording.add(
SimpleEvent(procedure: $event.location.procedure, state: event.newState)
)
var timeShifted = event
timeShifted.timestamp = fakeTime
rawRecording.add(timeShifted)
proc recordSegment*(segment: string) =
{.cast(gcsafe).}:
recording.add(SimpleEvent(procedure: segment, state: ExtendedFutureState.Running))
proc stopRecording*(): void =
recording = @[]
rawRecording = @[]
detachMonitoring()
proc startRecording*() =
stopRecording()
attachMonitoring(recordEvent)
proc forProc*(self: var MetricsTotals, procedure: string): AggregateMetrics =
for (key, aggMetrics) in self.mpairs:
if key.procedure == procedure:
return aggMetrics
proc resetTime*() =
fakeTime = Moment.now()
proc advanceTime*(duration: Duration) =
fakeTime += duration
proc advanceTimeAsync*(duration: Duration): Future[void] =
# Simulates a non-blocking operation that takes the provided duration to
# complete.
var retFuture = newFuture[void]("advanceTimeAsync")
var timer: TimerCallback
proc completion(data: pointer) {.gcsafe.} =
if not (retFuture.finished()):
advanceTime(duration)
retFuture.complete()
# The actual value for the timer is irrelevant, the important thing is that
# this causes the parent to pause before we advance time.
timer =
setTimer(Moment.fromNow(10.milliseconds), completion, cast[pointer](retFuture))
return retFuture