aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_windows.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing_windows.go')
-rw-r--r--src/testing/testing_windows.go38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/testing/testing_windows.go b/src/testing/testing_windows.go
index fd48ae9579..ebe4e01d23 100644
--- a/src/testing/testing_windows.go
+++ b/src/testing/testing_windows.go
@@ -9,7 +9,9 @@ package testing
import (
"errors"
"internal/syscall/windows"
+ "math/bits"
"syscall"
+ "time"
)
// isWindowsRetryable reports whether err is a Windows error code
@@ -30,3 +32,39 @@ func isWindowsRetryable(err error) bool {
}
return false
}
+
+// highPrecisionTime represents a single point in time with query performance counter.
+// time.Time on Windows has low system granularity, which is not suitable for
+// measuring short time intervals.
+//
+// TODO: If Windows runtime implements high resolution timing then highPrecisionTime
+// can be removed.
+type highPrecisionTime struct {
+ now int64
+}
+
+// highPrecisionTimeNow returns high precision time for benchmarking.
+func highPrecisionTimeNow() highPrecisionTime {
+ var t highPrecisionTime
+ // This should always succeed for Windows XP and above.
+ t.now = windows.QueryPerformanceCounter()
+ return t
+}
+
+func (a highPrecisionTime) sub(b highPrecisionTime) time.Duration {
+ delta := a.now - b.now
+
+ if queryPerformanceFrequency == 0 {
+ queryPerformanceFrequency = windows.QueryPerformanceFrequency()
+ }
+ hi, lo := bits.Mul64(uint64(delta), uint64(time.Second)/uint64(time.Nanosecond))
+ quo, _ := bits.Div64(hi, lo, uint64(queryPerformanceFrequency))
+ return time.Duration(quo)
+}
+
+var queryPerformanceFrequency int64
+
+// highPrecisionTimeSince returns duration since a.
+func highPrecisionTimeSince(a highPrecisionTime) time.Duration {
+ return highPrecisionTimeNow().sub(a)
+}