Skip to content

Commit

Permalink
Add timezone caching and use faster time primitives.
Browse files Browse the repository at this point in the history
  • Loading branch information
cheatfate committed Jun 18, 2024
1 parent 03301c0 commit 41c8ed6
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 24 deletions.
49 changes: 25 additions & 24 deletions chronicles/log_output.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import
strutils, times, macros, options, os,
strutils, times, macros, options, os, timestamp,
dynamic_scope_types, stew/[objects, byteutils]

when defined(js):
Expand Down Expand Up @@ -430,8 +430,9 @@ proc epochTimestamp: string =

var
cachedTime = dateTime(1900, mJan, 1)
cachedTimestamp = initTime(0'i64, 0)
cachedMinute = -1
cachedTimeArray: array[17, byte] # "yyyy-MM-dd HH:mm:"
cachedZonePeriod: int = -1
cachedZoneArray: array[6, byte] # "zzz"

template timeIsCached(a: DateTime): bool =
Expand All @@ -442,33 +443,33 @@ template timeIsCached(a: DateTime): bool =
else:
false

template timezoneIsCached(a: DateTime): bool =
if (ord(a.minute) div 15) == cachedZonePeriod:
true
proc getFastDateTimeString(): string =
let
timestamp = getFastTime()
diff = timestamp - cachedTimestamp
checkTime = cachedTime + diff

if not(checkTime.timeIsCached()):
cachedTimestamp = timestamp
cachedTime = timestamp.local()
block:
# Cache string representation of first part (without seconds)
let tmp = cachedTime.format("yyyy-MM-dd HH:mm:")
cachedTimeArray = toArray(17, tmp.toOpenArrayByte(0, 16))
block:
# Cache string representation of zone part
let tmp = cachedTime.format("zzz")
cachedZoneArray = toArray(6, tmp.toOpenArrayByte(0, 5))
else:
false

proc getTimeString(a: DateTime): string =
if not(timeIsCached(a)):
let tmp = a.format("yyyy-MM-dd HH:mm:")
cachedTime = a
cachedTimeArray = toArray(17, tmp.toOpenArrayByte(0, 16))
string.fromBytes(cachedTimeArray)

proc getZoneString(a: DateTime): string =
if not(timezoneIsCached(a)):
let tmp = a.format("zzz")
cachedZonePeriod = ord(a.minute) div 15
cachedZoneArray = toArray(6, tmp.toOpenArrayByte(0, 5))
string.fromBytes(cachedZoneArray)
cachedTime = checkTime
cachedTimestamp = timestamp

proc getSecondsString(a: DateTime): string =
a.format("ss'.'fff")
string.fromBytes(cachedTimeArray) & cachedTime.format("ss'.'fff") &
string.fromBytes(cachedZoneArray)

template timestamp(record): string =
when record.timestamps == RfcTime:
let ct = now()
getTimeString(ct) & getSecondsString(ct) & getZoneString(ct)
getFastDateTimeString()
else:
epochTimestamp()

Expand Down
40 changes: 40 additions & 0 deletions chronicles/timestamp.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

{.push raises: [].}

import std/times
export times

when defined(macos) or defined(macosx) or defined(osx):
from posix import gettimeofday, Timeval
elif defined(windows):
type
FILETIME {.final, pure, completeStruct.} = object
dwLowDateTime: uint32
dwHighDateTime: uint32
proc getSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var FILETIME) {.
importc: "GetSystemTimeAsFileTime", dynlib: "kernel32", stdcall,
sideEffect.}
else:
const CLOCK_REALTIME_COARSE = 5
from std/posix import Timespec, Time, clock_gettime

proc getFastTime*(): Time =
when defined(js):
let
millis = newDate().getTime()
seconds = millis div 1_000
nanos = (millis mod 1_000) * 1_000_000
initTime(seconds, nanos)
elif defined(macosx):
var a {.noinit.}: Timeval
gettimeofday(a)
initTime(a.tv_sec.int64, int(a.tv_usec) * 1_000)
elif defined(windows):
var f {.noinit.}: FILETIME
getSystemTimeAsFileTime(f)
let tmp = uint64(f.dwLowDateTime) or (uint64(f.dwHighDateTime) shl 32)
fromWinTime(cast[int64](tmp))
else:
var ts {.noinit.}: Timespec
discard clock_gettime(CLOCK_REALTIME_COARSE, ts)
initTime(int64(ts.tv_sec), int(ts.tv_nsec))

0 comments on commit 41c8ed6

Please sign in to comment.