From d073677569085642935d5d3b6acfe6df1054ae21 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Fri, 31 Aug 2012 20:17:59 +1000 Subject: [PATCH] cgo/misc/test: burn CPU to improve sleep accuracy Fixes #4008. Run a background goroutine that wastes CPU to trick the power management into raising the CPU frequency which, by side effect, makes sleep more accurate on arm. === RUN TestParallelSleep --- PASS: TestParallelSleep (1.30 seconds) _cgo_gotypes.go:772: sleep(1) slept for 1.000458s R=minux.ma, r CC=golang-dev https://golang.org/cl/6498060 --- misc/cgo/test/issue1560.go | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/misc/cgo/test/issue1560.go b/misc/cgo/test/issue1560.go index 7bc1dd6df49..ac897aa33bf 100644 --- a/misc/cgo/test/issue1560.go +++ b/misc/cgo/test/issue1560.go @@ -35,16 +35,35 @@ func BackgroundSleep(n int) { }() } +// wasteCPU starts a background goroutine to waste CPU +// to cause the power management to raise the CPU frequency. +// On ARM this has the side effect of making sleep more accurate. +func wasteCPU() chan struct{} { + done := make(chan struct{}) + go func() { + for { + select { + case <-done: + return + default: + } + } + }() + // pause for a short amount of time to allow the + // power management to recognise load has risen. + <-time.After(300 * time.Millisecond) + return done +} + func testParallelSleep(t *testing.T) { + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2)) + defer close(wasteCPU()) + sleepSec := 1 - if runtime.GOARCH == "arm" { - // on ARM, the 1.3s deadline is frequently missed, - // so increase sleep time to 2s - sleepSec = 2 - } start := time.Now() parallelSleep(sleepSec) - dt := time.Now().Sub(start) + dt := time.Since(start) + t.Logf("sleep(%d) slept for %v", sleepSec, dt) // bug used to run sleeps in serial, producing a 2*sleepSec-second delay. if dt >= time.Duration(sleepSec)*1300*time.Millisecond { t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds())