[feature] Added std/monotimes
This commit is contained in:
parent
b8be1ccb85
commit
fd24a8923e
5 changed files with 183 additions and 1 deletions
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
- Make public `Sha1Digest` and `Sha1State` types and `newSha1State`, `update` and `finalize` procedures from `sha1` module. (#11694)
|
- Make public `Sha1Digest` and `Sha1State` types and `newSha1State`, `update` and `finalize` procedures from `sha1` module. (#11694)
|
||||||
|
|
||||||
|
- Added the `std/monotimes` module which implements monotonic timestamps.
|
||||||
|
|
||||||
## Language additions
|
## Language additions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,10 @@ Generic Operating System Services
|
||||||
Module for process communication beyond ``os.execShellCmd``.
|
Module for process communication beyond ``os.execShellCmd``.
|
||||||
|
|
||||||
* `times <times.html>`_
|
* `times <times.html>`_
|
||||||
The ``times`` module contains basic support for working with time.
|
The ``times`` module contains support for working with time.
|
||||||
|
|
||||||
|
* `std/monotimes <monotimes.html>`_
|
||||||
|
The `monotimes` module implements monotonic timestamps.
|
||||||
|
|
||||||
* `dynlib <dynlib.html>`_
|
* `dynlib <dynlib.html>`_
|
||||||
This module implements the ability to access symbols from shared libraries.
|
This module implements the ability to access symbols from shared libraries.
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,10 @@
|
||||||
day has passed. The ``Duration`` type on the other hand normalizes everything
|
day has passed. The ``Duration`` type on the other hand normalizes everything
|
||||||
to seconds, and will therefore say that 90000 seconds has passed, which is
|
to seconds, and will therefore say that 90000 seconds has passed, which is
|
||||||
the same as 25 hours.
|
the same as 25 hours.
|
||||||
|
|
||||||
|
See also
|
||||||
|
========
|
||||||
|
* `monotimes module <monotimes.html>`_
|
||||||
]##
|
]##
|
||||||
|
|
||||||
import strutils, math, options
|
import strutils, math, options
|
||||||
|
|
|
||||||
173
lib/std/monotimes.nim
Normal file
173
lib/std/monotimes.nim
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Nim's Runtime Library
|
||||||
|
# (c) Copyright 2019 Nim contributors
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
##[
|
||||||
|
The ``std/monotimes`` module implements monotonic timestamps. A monotonic
|
||||||
|
timestamp represents the time that has passed since some system defined
|
||||||
|
point in time. The monotonic timestamps are guaranteed to always increase,
|
||||||
|
meaning that that the following is guaranteed to work:
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
let a = getMonoTime()
|
||||||
|
# ... do some work
|
||||||
|
let b = getMonoTime()
|
||||||
|
assert a <= b
|
||||||
|
|
||||||
|
This is not guaranteed for the `times.Time` type! This means that the
|
||||||
|
`MonoTime` should be used when measuring durations of time with
|
||||||
|
high precision.
|
||||||
|
|
||||||
|
However, since `MonoTime` represents the time that has passed since some
|
||||||
|
unknown time origin, it cannot be converted to a human readable timestamp.
|
||||||
|
If this is required, the `times.Time` type should be used instead.
|
||||||
|
|
||||||
|
The `MonoTime` type stores the timestamp in nanosecond resolution, but note
|
||||||
|
that the actual supported time resolution differs for different systems.
|
||||||
|
|
||||||
|
See also
|
||||||
|
========
|
||||||
|
* `times module <times.html>`_
|
||||||
|
]##
|
||||||
|
|
||||||
|
import times
|
||||||
|
|
||||||
|
type
|
||||||
|
MonoTime* = object ## Represents a monotonic timestamp.
|
||||||
|
ticks: int64
|
||||||
|
|
||||||
|
when defined(macosx):
|
||||||
|
type
|
||||||
|
MachTimebaseInfoData {.pure, final, importc: "mach_timebase_info_data_t",
|
||||||
|
header: "<mach/mach_time.h>".} = object
|
||||||
|
numer, denom: int32
|
||||||
|
|
||||||
|
proc mach_absolute_time(): int64 {.importc, header: "<mach/mach.h>".}
|
||||||
|
proc mach_timebase_info(info: var MachTimebaseInfoData) {.importc,
|
||||||
|
header: "<mach/mach_time.h>".}
|
||||||
|
|
||||||
|
let machAbsoluteTimeFreq = block:
|
||||||
|
var freq: MachTimebaseInfoData
|
||||||
|
mach_timebase_info(freq)
|
||||||
|
freq
|
||||||
|
|
||||||
|
when defined(js):
|
||||||
|
proc getJsTicks: float =
|
||||||
|
{.emit: """
|
||||||
|
var isNode = typeof module !== 'undefined' && module.exports
|
||||||
|
|
||||||
|
if (isNode) {
|
||||||
|
var process = require('process');
|
||||||
|
var time = process.hrtime()
|
||||||
|
return time[0] + time[1] / 1000000000;
|
||||||
|
} else {
|
||||||
|
return window.performance.now() * 1000000;
|
||||||
|
}
|
||||||
|
""".}
|
||||||
|
|
||||||
|
# Workaround for #6752.
|
||||||
|
{.push overflowChecks: off.}
|
||||||
|
proc `-`(a, b: int64): int64 =
|
||||||
|
system.`-`(a, b)
|
||||||
|
proc `+`(a, b: int64): int64 =
|
||||||
|
system.`+`(a, b)
|
||||||
|
{.pop.}
|
||||||
|
|
||||||
|
elif defined(posix):
|
||||||
|
import posix
|
||||||
|
|
||||||
|
elif defined(windows):
|
||||||
|
proc QueryPerformanceCounter(res: var uint64) {.
|
||||||
|
importc: "QueryPerformanceCounter", stdcall, dynlib: "kernel32".}
|
||||||
|
proc QueryPerformanceFrequency(res: var uint64) {.
|
||||||
|
importc: "QueryPerformanceFrequency", stdcall, dynlib: "kernel32".}
|
||||||
|
|
||||||
|
let queryPerformanceCounterFreq = block:
|
||||||
|
var freq: uint64
|
||||||
|
QueryPerformanceFrequency(freq)
|
||||||
|
1_000_000_000'u64 div freq
|
||||||
|
|
||||||
|
proc getMonoTime*(): MonoTime {.tags: [TimeEffect].} =
|
||||||
|
## Get the current `MonoTime` timestamp.
|
||||||
|
##
|
||||||
|
## When compiled with the JS backend and executed in a browser,
|
||||||
|
## this proc calls `window.performance.now()`, which is not supported by
|
||||||
|
## older browsers. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now)
|
||||||
|
## for more information.
|
||||||
|
when defined(JS):
|
||||||
|
let ticks = getJsTicks()
|
||||||
|
result = MonoTime(ticks: (ticks * 1_000_000_000).int64)
|
||||||
|
elif defined(macosx):
|
||||||
|
let ticks = mach_absolute_time()
|
||||||
|
result = MonoTime(ticks: ticks * machAbsoluteTimeFreq.numer div
|
||||||
|
machAbsoluteTimeFreq.denom)
|
||||||
|
elif defined(posix):
|
||||||
|
var ts: Timespec
|
||||||
|
discard clock_gettime(CLOCK_MONOTONIC, ts)
|
||||||
|
result = MonoTime(ticks: ts.tv_sec.int64 * 1_000_000_000 +
|
||||||
|
ts.tv_nsec.int64)
|
||||||
|
elif defined(windows):
|
||||||
|
var ticks: uint64
|
||||||
|
QueryPerformanceCounter(ticks)
|
||||||
|
result = MonoTime(ticks: (ticks * queryPerformanceCounterFreq).int64)
|
||||||
|
|
||||||
|
proc ticks*(t: MonoTime): int64 =
|
||||||
|
## Returns the raw ticks value from a `MonoTime`. This value always uses
|
||||||
|
## nanosecond time resolution.
|
||||||
|
t.ticks
|
||||||
|
|
||||||
|
proc `$`*(t: MonoTime): string =
|
||||||
|
$t.ticks
|
||||||
|
|
||||||
|
proc `-`*(a, b: MonoTime): Duration =
|
||||||
|
## Returns the difference between two `MonoTime` timestamps as a `Duration`.
|
||||||
|
initDuration(nanoseconds = (a.ticks - b.ticks))
|
||||||
|
|
||||||
|
proc `+`*(a: MonoTime, b: Duration): MonoTime =
|
||||||
|
## Increases `a` by `b`.
|
||||||
|
MonoTime(ticks: a.ticks + b.inNanoseconds)
|
||||||
|
|
||||||
|
proc `-`*(a: MonoTime, b: Duration): MonoTime =
|
||||||
|
## Reduces `a` by `b`.
|
||||||
|
MonoTime(ticks: a.ticks - b.inNanoseconds)
|
||||||
|
|
||||||
|
proc `<`*(a, b: MonoTime): bool =
|
||||||
|
## Returns true if `a` happened before `b`.
|
||||||
|
a.ticks < b.ticks
|
||||||
|
|
||||||
|
proc `<=`*(a, b: MonoTime): bool =
|
||||||
|
## Returns true if `a` happened before `b` or if they happened simultaneous.
|
||||||
|
a.ticks <= b.ticks
|
||||||
|
|
||||||
|
proc `==`*(a, b: MonoTime): bool =
|
||||||
|
## Returns true if `a` and `b` happened simultaneous.
|
||||||
|
a.ticks == b.ticks
|
||||||
|
|
||||||
|
proc high*(typ: typedesc[MonoTime]): MonoTime =
|
||||||
|
## Returns the highest representable `MonoTime`.
|
||||||
|
MonoTime(ticks: high(int64))
|
||||||
|
|
||||||
|
proc low*(typ: typedesc[MonoTime]): MonoTime =
|
||||||
|
## Returns the lowest representable `MonoTime`.
|
||||||
|
MonoTime(ticks: low(int64))
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
let d = initDuration(nanoseconds = 10)
|
||||||
|
let t1 = getMonoTime()
|
||||||
|
let t2 = t1 + d
|
||||||
|
|
||||||
|
doAssert t2 - t1 == d
|
||||||
|
doAssert t1 == t1
|
||||||
|
doAssert t1 != t2
|
||||||
|
doAssert t2 - d == t1
|
||||||
|
doAssert t1 < t2
|
||||||
|
doAssert t1 <= t2
|
||||||
|
doAssert t1 <= t1
|
||||||
|
doAssert not(t2 < t1)
|
||||||
|
doAssert t1 < high(MonoTime)
|
||||||
|
doAssert low(MonoTime) < t1
|
||||||
|
|
@ -158,6 +158,7 @@ lib/windows/winlean.nim
|
||||||
lib/pure/random.nim
|
lib/pure/random.nim
|
||||||
lib/pure/complex.nim
|
lib/pure/complex.nim
|
||||||
lib/pure/times.nim
|
lib/pure/times.nim
|
||||||
|
lib/std/monotimes.nim
|
||||||
lib/pure/osproc.nim
|
lib/pure/osproc.nim
|
||||||
lib/pure/pegs.nim
|
lib/pure/pegs.nim
|
||||||
lib/pure/dynlib.nim
|
lib/pure/dynlib.nim
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue