//go:build unix package cpu // #include import "C" import ( "runtime" "time" ) var cpuCount = runtime.GOMAXPROCS(0) // probe the CPU usage of the process // if CPUs are not busy, most threads are likely waiting for I/O, so we should scale // if CPUs are already busy we won't gain much by scaling and want to avoid the overhead of doing so func ProbeCPUs(probeTime time.Duration, maxCPUUsage float64, abort chan struct{}) bool { var cpuStart, cpuEnd C.struct_timespec // note: clock_gettime is a POSIX function // on Windows we'd need to use QueryPerformanceCounter instead start := time.Now() C.clock_gettime(C.CLOCK_PROCESS_CPUTIME_ID, &cpuStart) select { case <-abort: return false case <-time.After(probeTime): } C.clock_gettime(C.CLOCK_PROCESS_CPUTIME_ID, &cpuEnd) elapsedTime := float64(time.Since(start).Nanoseconds()) elapsedCpuTime := float64(cpuEnd.tv_sec-cpuStart.tv_sec)*1e9 + float64(cpuEnd.tv_nsec-cpuStart.tv_nsec) cpuUsage := elapsedCpuTime / elapsedTime / float64(cpuCount) return cpuUsage < maxCPUUsage }