简体   繁体   中英

Prevent excessive CPU usage of Golang background process

I am writing a Go program that watches files and run a system command if one of the files has changed. So far, it works well. I have questions regarding my main "infinite" loop because I don't want it to take all system CPU resources:

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)
    }
}

So, what I have done is setting GOMAXPROCS, so it only uses "1 CPU/Core", and I have added a configurable sleep time in the else branch.

Without the sleep time, htop shows that the process takes 100% of CPU time (I guess it is 100% of one core?) whatever If I call runtime.GOMAXPROCS(1) or not.

If I use a sleep time of 30ms on my machine (MacMini i7, 12 Core) htop reports 20% CPU utilisation from the process, which seems OK, but I guess this will vary depending on the computer running the program.

What is the best practice here?

GOMAXPROCS does not what you think it does. From package runtime docu:

The GOMAXPROCS variable limits the number of operating system threads that can execute user-level Go code simultaneously. There is no limit to the number of threads that can be blocked in system calls on behalf of Go code; those do not count against the GOMAXPROCS limit.

It limits OS threads. If your code doesn't use goroutines which could be scheduled to OS threads limiting the number of threads does literally nothing . Just remove the GOMAXPROCS stuff, it does nothing. (If you set GOMAXPROCS to 12 you will have at most 12 OS threads actually executing goroutine code; If you have just one goroutine limiting the number of OS threads it can run on is a noop.)

All you can do is not busy-looping as you did with time.Sleep(). Depending on your requirements you could call the actual code regularly, eg via a time.Ticker. There is no single "best practice" (excepet not fiddling with GOMAXPROCS).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM