Skip to content

Instantly share code, notes, and snippets.

@jimwei
Created January 13, 2016 00:55
Show Gist options
  • Save jimwei/c16e09bd9353e425a3d1 to your computer and use it in GitHub Desktop.
Save jimwei/c16e09bd9353e425a3d1 to your computer and use it in GitHub Desktop.

Revisions

  1. jimwei created this gist Jan 13, 2016.
    133 changes: 133 additions & 0 deletions stopwatch.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,133 @@
    package main

    import (
    "syscall"
    "time"
    "unsafe"
    )

    const (
    TickPerMillisecond int64 = 0x2710
    TicksPerSecond int64 = 0x989680
    )

    var (
    modkernel32 = syscall.NewLazyDLL("kernel32.dll")
    procQueryPerformanceFrequency = modkernel32.NewProc("QueryPerformanceFrequency")
    procQueryPerformanceCounter = modkernel32.NewProc("QueryPerformanceCounter")
    procSleep = modkernel32.NewProc("Sleep")
    )

    type stopWatch struct {
    elapsed int64
    startTimeStamp int64
    isRunning bool
    start time.Time
    IsHighResolution bool
    Frequery int64
    tickFrequery float64
    }

    func NewStopWatch() *stopWatch {
    sw := new(stopWatch)
    if err := queryPerformanceFrequency(&sw.Frequery); err != nil {
    sw.IsHighResolution = false
    sw.Frequery = 0x989680
    sw.tickFrequery = 1.0
    } else {
    sw.IsHighResolution = true
    sw.tickFrequery = 10000000.0
    sw.tickFrequery /= float64(sw.Frequery)
    }
    return sw

    }
    func StartNew() *stopWatch {
    sw := new(stopWatch)
    sw.Start()
    return sw
    }
    func (this *stopWatch) Reset() {
    this.elapsed = 0
    this.startTimeStamp = 0
    this.isRunning = false
    }
    func (this *stopWatch) Start() {
    if !this.isRunning {
    this.startTimeStamp = this.getTimestamp()
    this.isRunning = true
    }
    }
    func (this *stopWatch) Stop() {
    if this.isRunning {
    num2 := this.getTimestamp() - this.startTimeStamp
    this.elapsed += num2
    this.isRunning = false
    }
    }
    func (this *stopWatch) Elapsed() int64 {
    return this.getElapsedDateTimeTicks()
    }
    func (this *stopWatch) ElapsedMilliseconds() int64 {
    return this.getElapsedDateTimeTicks() / 0x2710
    }
    func (this *stopWatch) ElapsedTicks() int64 {
    return this.getRawElapsedTicks()
    }
    func (this *stopWatch) IsRunning() bool {
    return this.isRunning
    }
    func (this *stopWatch) getElapsedDateTimeTicks() int64 {
    rawElapsedTicks := this.getRawElapsedTicks()
    if this.IsHighResolution {
    num2 := float64(rawElapsedTicks)
    num2 *= this.tickFrequery
    return int64(num2)
    }
    return rawElapsedTicks
    }
    func (this *stopWatch) getRawElapsedTicks() int64 {
    elapsed := this.elapsed
    if this.isRunning {
    num3 := this.getTimestamp() - this.startTimeStamp
    elapsed += num3
    }
    return elapsed
    }
    func (this *stopWatch) getTimestamp() int64 {
    if this.IsHighResolution {
    var num int64
    queryPerformanceCounter(&num)
    return num
    }
    return time.Now().UTC().Unix()
    }

    func queryPerformanceFrequency(frequency *int64) (err error) {
    r1, _, e1 := syscall.Syscall(procQueryPerformanceFrequency.Addr(), 1, uintptr(unsafe.Pointer(frequency)), 0, 0)
    if r1 == 0 {
    if e1 != 0 {
    err = error(e1)
    } else {
    err = syscall.EINVAL
    }
    }
    return
    }

    func queryPerformanceCounter(counter *int64) (err error) {
    r1, _, e1 := syscall.Syscall(procQueryPerformanceCounter.Addr(), 1, uintptr(unsafe.Pointer(counter)), 0, 0)
    if r1 == 0 {
    if e1 != 0 {
    err = error(e1)
    } else {
    err = syscall.EINVAL
    }
    }
    return
    }

    func sleep(milliseconds uint32) {
    syscall.Syscall(procSleep.Addr(), 1, uintptr(milliseconds), 0, 0)
    return
    }