我正在编写一个Go程序,该程序监视文件并在其中一个文件已更改的情况下运行系统命令。到目前为止,它运行良好。我对主“无限”循环有疑问,因为我不想让它占用所有系统CPU资源:
runtime.GOMAXPROCS(1)
for {
updatedFiles, _ := GetWatchMap(config)
if !reflect.DeepEqual(filesToWatch, updatedFiles) {
start := time.Now()
_, _ = colorstring.Println(fmt.Sprintf(" [yellow] ⬇ Update detected[white] at [green]%s[white] > updating...", start.Format("15:04:05")))
_, _ = Update(config)
end := time.Now()
elapsed := end.Sub(start)
_, _ = colorstring.Println(fmt.Sprintf(" [green]✅ Done![white] in [yellow]%.2f[white] second(s).", elapsed.Seconds()))
filesToWatch = updatedFiles
} else {
time.Sleep(config.SleepTime)
}
}
因此,我所做的是设置GOMAXPROCS,因此它仅使用“ 1 CPU / Core”,并且我在else分支中添加了可配置的睡眠时间。
[如果没有调用runtime.GOMAXPROCS(1)
,无论是否调用,htop都会显示该进程占用100%的CPU时间(我猜它是一个内核的100%?)。
如果我在计算机(MacMini i7,12核)上使用30ms的睡眠时间,则htop报告该进程的CPU利用率为20%,这似乎还可以,但是我猜这会因运行该程序的计算机而异。
这里的最佳做法是什么?
GOMAXPROCS并非您认为的那样。从程序包运行时文档中:
GOMAXPROCS变量限制了可以同时执行用户级Go代码的操作系统线程的数量。对于代表Go代码的系统调用中可以阻止的线程数量没有限制;那些不计入GOMAXPROCS限制。
它限制了操作系统线程。如果您的代码不使用goroutines,则could会被安排到OS线程中,因此实际上限制了线程的数量是[[nothing。只需删除GOMAXPROCS内容,它什么也不会做。 (如果将GOMAXPROCS设置为12,则实际上最多有12个OS线程实际在执行goroutine代码;如果只有一个goroutine限制了可以在其上运行的OS线程的数量,则为noop。)
您所能做的就是不像使用time.Sleep()那样忙循环。根据您的
要求,您可以定期调用实际代码,例如通过时间。没有单一的“最佳实践”(例外不喜欢GOMAXPROCS)。