I tested all possible candidate APIs again. This program:
package main
import (
"fmt"
"runtime"
"syscall"
"unsafe"
)
var (
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetTickCount64 = modkernel32.NewProc("GetTickCount64")
procGetTickCount = modkernel32.NewProc("GetTickCount")
)
func GetTickCount64() uint64 {
r, _, _ := syscall.Syscall(procGetTickCount64.Addr(), 0, 0, 0, 0)
return uint64(r)
}
func GetTickCount() uint32 {
r, _, _ := syscall.Syscall(procGetTickCount.Addr(), 0, 0, 0, 0)
return uint32(r)
}
func getSystemTimeAsFileTime() uint64 {
var ft syscall.Filetime
syscall.GetSystemTimeAsFileTime(&ft)
return uint64(ft.Nanoseconds())
}
func getTickCount() uint64 {
return uint64(GetTickCount()) * 1000000
}
func getTickCount64() uint64 {
return GetTickCount64() * 1000000
}
type KSYSTEM_TIME struct {
LowPart uint32
High1Time int32
High2Time int32
}
var (
// KUSER_SHARED_DATA
interruptTimeAddr =
(*KSYSTEM_TIME)(unsafe.Pointer(uintptr(0x7FFE0008)))
systemTimeAddr =
(*KSYSTEM_TIME)(unsafe.Pointer(uintptr(0x7FFE0014)))
)
func readUSD(addr *KSYSTEM_TIME) uint64 {
var t KSYSTEM_TIME
for i := 0; ; i++ {
t.High1Time = addr.High1Time
t.LowPart = addr.LowPart
t.High2Time = addr.High2Time
if t.High1Time == t.High2Time {
break
}
if i > 100 {
panic("should have advanced by now")
}
}
return *((*uint64)(unsafe.Pointer(&t))) * 100
}
func readInterruptTime() uint64 {
return readUSD(interruptTimeAddr)
}
func readSystemTime() uint64 {
return readUSD(systemTimeAddr)
}
func getprec(getticks func() uint64) []uint64 {
r := make([]uint64, 0)
c := getticks()
for i := 0; i < 5; {
c2 := getticks()
if c != c2 {
r = append(r, c2-c)
i++
}
}
return r
}
func main() {
fmt.Printf("getSystemTimeAsFileTime: %v\n",
getprec(getSystemTimeAsFileTime))
fmt.Printf("getTickCount : %v\n", getprec(getTickCount))
if runtime.GOARCH == "amd64" {
fmt.Printf("getTickCount64 : %v\n", getprec(getTickCount64))
}
fmt.Printf("readInterruptTime : %v\n", getprec(readInterruptTime))
fmt.Printf("readSystemTime : %v\n", getprec(readSystemTime))
}
prints
C:\>u:\test
getSystemTimeAsFileTime: [15625000 15625000 15625000 15625000 15625000]
getTickCount : [15000000 15000000 15000000 15000000 15000000]
readInterruptTime : [976600 976600 976600 976600 976600]
readSystemTime : [15625000 15625000 15625000 15625000 15625000]
on windows xp, and
C:\>u:\test
getSystemTimeAsFileTime: [977000 977000 977000 977000 977000]
getTickCount : [16000000 16000000 16000000 16000000 16000000]
getTickCount64 : [15000000 15000000 15000000 15000000 15000000]
readInterruptTime : [976500 976500 976500 976500 976500]
readSystemTime : [977000 977000 977000 977000 977000]
on windows 7.
I still haven't made my mind about what to use here, so any suggestions
are welcome.
Alex
https://codereview.appspot.com/108700045/