Reputation: 189
I have this loop that what it does is trying to repeatedly poll to another server. I used ticker to achieve this however the program repeatedly shows 100% CPU usage.
This ticker runs inside a goroutine. and the HTTP server runs inside another goroutine.
func() Monitor() {
abort := make(chan bool)
log.Info("Monitor started.")
// start the monitor goroutine
go func() {
defer log.Info("Stopped monitor")
ticker := time.NewTicker(time.Duration(35.0) * time.Second)
defer ticker.Stop()
log.Info("Monitor started! \n")
for {
select {
case t := <-ticker.C:
log.Infof("Subscribe to service at time %v\n", t)
if err := selfConn.SubscribeToService(); err != nil {
log.Errorf("Failed to subscribe to primary connector: %v", err)
}
case <-abort:
log.Info("Finished routine!")
return
default:
continue
}
}
}()
go func() {
time.Sleep(10 * time.Minute)
abort <- true
}()
}
However when monitor loops start, and everytime the signal to the ticker channel is sent, the CPU shows 100% constantly.
What have I missed in using ticker in the goroutine so that it won't consume 100% CPU?
Upvotes: 1
Views: 2572
Reputation: 418407
You have a select
with a default
branch inside your loop. If none of the other case
s are ready to proceed, the default
branch is executed immediately, so your next iteration begins immediately without wait. This is a busy loop.
Also, there is no need for another goroutine to terminate, you could use a timer for that in the same goroutine.
For example:
func monitor() {
log.Info("Monitor started.")
ticker := time.NewTicker(35 * time.Second)
defer ticker.Stop()
timeoutCh := time.After(10 * time.Minute)
for {
select {
case t := <-ticker.C:
log.Infof("Subscribe to service at time %v\n", t)
if err := selfConn.SubscribeToService(); err != nil {
log.Errorf("Failed to subscribe to primary connector: %v", err)
}
case <-timeoutCh:
log.Info("Finished routine!")
return
}
}
}
Upvotes: 12