Get unix time (nanoseconds) in blazing low latency with high precision. About 6x~10x faster than time.Now().UnixNano().
Could accelerate Cloud-Native applications too! See this for details.
It's not a good idea to use this lib for replacing system clock everywhere, before using it please read this documents carefully.
We want everything is fast in stock trading program (especially the speed of making money :D). Before marketing opens, we use NTP to force update machine's system clock, then the program run with this lib will get a good starting, the drift will be under control well if the frequency used by system is good enough.
In this case, we could allow out-of-order for higher speed. Out-of-order could be ~10ns faster than in order version, it's important for trading function which total cost is within hundreds nanoseconds. Out-of-order may bring dozens nanoseconds jitter, not big deal for this case because what we want is just a faster timestamp for logging something.
For this case, we need in-order version for avoiding unexpected instructions going inside the function which we want to measure the speed.
func Calibrate()
in tsc_amd64.goadjtimex
too, Calibrate()
will try best to catch up the changes made by kernel.If I could do better in tsc frequency detection & precision, shouldn't be a good idea that ignore kernel clock?
First, as I mentioned above I need to borrow the abilities of calibration which help to make kernel clock better. The crystal of TSC is not as good as we expect, it's just a cheap crystal, we need adjust the frequency result time by time.
Second, it'll make people confused if there are two different clocks and their results are quietly different.
Testing the delta of tsc clock & system clock for each second.
platform: macOS Catalina, Intel Core i7-7700HQ
measurement: tools/longdrift with default flags.
p.s.
platform: Ubuntu 18.04, Intel Core i5-8250U
measurement: tools/longdrift with default flags.
p.s.
It's a cheap laptop, the result is not that good. We could find the crystal frequency wasn't stable enough, the time sync service really worked hard. For tsc, it's a hard job to catch up the clock too.
OS | CPU | time.Now().UnixNano() ns/op | tsc.UnixNano() ns/op | delta |
---|---|---|---|---|
macOS Catalina | Intel Core i7-7700HQ | 72.8 | 7.65 | -89.49% |
Ubuntu 18.04 | Intel Core i5-8250U | 47.7 | 8.41 | -82.36% |
Ubuntu 20.04 | Intel Core i9-9920X | 36.5 | 6.19 | -83.04% |
Fedora 40 | Intel Core i7-12700K | 22.34 | 5.81 | -73.99% |
The new ABI in Go1.17 brings register-based calling, but for assembly codes there is an adapter, it degrades performance around 0.x ns.
Waiting for ABI option to use register-based calling...
package main
import (
"fmt"
"github.com/templexxx/tsc"
)
func main() {
ts := tsc.UnixNano() // Getting unix nano timestamp.
fmt.Println(ts, tsc.Supported()) // Print result & tsc supported or not.
}
If tsc.Supported() == true
, it'll use tsc register. If not, it'll wrap time.Now().UnixNano()
.
tsc.Calibrate()
periodically if you need to catch up system clock. 5 mins is a good start because the auto NTP adjust is always every 11 mins.tsc.ForbidOutOfOrder()
when you need to measure time cost for short statements.On vm, the CPU feature detection may cannot work as expect because the CPUID limitation, the Invariant TSC feature cannot be detected if so.
But if the tsc is the system clock source which means this cloud provider could handle tsc clock source well enough, in that situation this lib will enable TSC as clock source too.
Some cloud vm could support tsc as clock source, e.g., AWS EC2, this lib could work well with these clouds.
Please contact your vm supports team to make sure the tsc clock source is reliable before using it.