bad practice: busy-waiting
Busy-waiting is one of the easiest ways of exhausting a cpu1:
package main
func main() {
for true {
/* complex logic */
}
}
What looks like an obvious bad construct one would never do by accident is often introduced on waiting for a resource or state change. One common place where such constructs are used is on reconnecting to a service.
Analyze
Use top
:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1237306 evilcookie 20 0 702424 936 644 R 100.3 0.0 0:59.39 busywaiting
The process has a load of one or higher.
Solutions
A general solution for busy-waiting is telling the CPU to do something else for
some time using the syscall sleep
2:
package main
import "time"
func main() {
for true {
/* complex logic */
time.Sleep(1 * time.Millisecond)
}
}
Sleeping one millisecond is enough to make the process barely obervable:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1242442 rpour 20 0 702476 1340 840 S 8.6 0.0 0:01.05 busywaiting
- all examples are written in golang
- sleep (3): “On Linux, sleep() is implemented via nanosleep(2).”