github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/bench/qpc/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "syscall" 6 "time" 7 "unsafe" 8 ) 9 10 // precision timing 11 var ( 12 modkernel32 = syscall.NewLazyDLL("kernel32.dll") 13 procQueryPerformanceFrequency = modkernel32.NewProc("QueryPerformanceFrequency") 14 procQueryPerformanceCounter = modkernel32.NewProc("QueryPerformanceCounter") 15 ) 16 17 func asmQPC() int64 18 19 var ( 20 _QueryPerformanceFrequency uintptr 21 _QueryPerformanceCounter uintptr 22 ) 23 24 type stdFunction unsafe.Pointer 25 26 // now returns time.Duration using queryPerformanceCounter 27 func QPC() int64 { 28 var now int64 29 syscall.Syscall(procQueryPerformanceCounter.Addr(), 1, uintptr(unsafe.Pointer(&now)), 0, 0) 30 return now 31 } 32 33 // now returns time.Duration using queryPerformanceCounter 34 func QPC2() int64 { 35 var now int64 36 syscall.SyscallN(procQueryPerformanceCounter.Addr(), uintptr(unsafe.Pointer(&now))) 37 return now 38 } 39 40 // QPCFrequency returns frequency in ticks per second 41 func QPCFrequency() int64 { 42 var freq int64 43 r1, _, _ := syscall.Syscall(procQueryPerformanceFrequency.Addr(), 1, uintptr(unsafe.Pointer(&freq)), 0, 0) 44 if r1 == 0 { 45 panic("call failed") 46 } 47 return freq 48 } 49 50 func main() { 51 _QueryPerformanceFrequency = procQueryPerformanceFrequency.Addr() 52 _QueryPerformanceCounter = procQueryPerformanceCounter.Addr() 53 const N = 10000000 54 55 { 56 start := QPC() 57 for i := 0; i < N; i++ { 58 QPC() 59 } 60 finish := QPC() 61 fmt.Println("QPC", delta(finish, start)/N) 62 } 63 64 { 65 start := QPC() 66 for i := 0; i < N; i++ { 67 QPC2() 68 } 69 finish := QPC() 70 fmt.Println("QPC2", delta(finish, start)/N) 71 } 72 73 { 74 start := QPC() 75 for i := 0; i < N; i++ { 76 asmQPC() 77 } 78 79 finish := QPC() 80 fmt.Println("asmQPC", delta(finish, start)/N) 81 fmt.Println("check", asmQPC()-QPC()) 82 } 83 84 { 85 start := QPC() 86 for i := 0; i < N; i++ { 87 time.Now() 88 } 89 finish := QPC() 90 fmt.Println("time.Now", delta(finish, start)/N) 91 } 92 } 93 94 func delta(a, b int64) time.Duration { 95 return time.Duration(a-b) * time.Second / (time.Duration(QPCFrequency()) * time.Nanosecond) 96 }