github.com/muyo/sno@v1.2.1/internal/time.go (about) 1 //go:build !(windows && amd64) && !(linux && amd64 && go1.17) 2 // +build !windows !amd64 3 // +build !linux !amd64 !go1.17 4 5 package internal 6 7 import _ "unsafe" // Required for go:linkname 8 9 // ostime returns the current wall clock time reported by the OS. 10 // 11 // The function is linked against runtime.walltime() directly, which is only available since the 12 // introduction of faketime in Go 1.14 (which is the version sno depends on at minimum). This being 13 // linked to an internal function instead of a semi-stable one like time.now() is somewhat brittle, 14 // but the rationale is explained below. 15 // 16 // POSIXy arch/OS combinations use some form of clock_gettime with CLOCK_REALTIME, either through 17 // a syscall, libc call (Darwin) or vDSO (Linux). 18 // These calls are relatively slow, even using vDSO. Not using time.Now() allows us to bypass getting 19 // the monotonic clock readings which is a separate invocation of the underlying kernel facility and 20 // roughly doubles the execution time. 21 // 22 // As a result, doing sno.New(0).Time() tends to be actually faster on those platforms than time.Now(), 23 // despite an entire ID being generated alongside. That is, if you're fine with the precision reduced to 4ms. 24 // 25 // On Windows/amd64 we use an even more efficient implementation which allows us to also bypass 26 // some unnecessary unit conversions, which isn't as trivially possible on POSIXy systems (as their 27 // kernels keep track of time and provide secs and fractional secs instead of a singular higher 28 // resolution source). 29 // 30 // See https://lore.kernel.org/linux-arm-kernel/20190621095252.32307-1-vincenzo.frascino@arm.com 31 // to get an overview of the perf numbers involved on Linux-based distros. 32 // 33 //go:linkname ostime runtime.walltime 34 func ostime() (sec int64, nsec int32) 35 36 // Snotime returns the current wall clock time reported by the OS as adjusted to our internal epoch. 37 func Snotime() uint64 { 38 wallSec, wallNsec := ostime() 39 40 return (uint64(wallSec)*1e9 + uint64(wallNsec) - epochNsec) / timeUnit 41 }