for и загрузка процессора
Собственно вопрос понятен из названия: Есть программа с несколькими гоурутинами которые работают одновременно и постоянно и которым надо посылать друг в друга уведомления. сейчас это:
botNotification := make(chan Notification, 1)
notification := Notification{Code: 1, TelegramID: user.TelegramID}
botNotification <- notification
for {
select {
case notification := <-botNotification:
switch notification.Code {
case 1:
c.SendChatAction(notification.TelegramID, tbot.ActionTyping)
time.Sleep(1 * time.Second)
c.SendMessage(notification.TelegramID, translation.ManagerOpened)
case 2:
c.SendChatAction(notification.TelegramID, tbot.ActionTyping)
time.Sleep(1 * time.Second)
c.SendMessage(notification.TelegramID, translation.AdminOpened)
default:
c.SendChatAction(notification.TelegramID, tbot.ActionTyping)
time.Sleep(1 * time.Second)
c.SendMessage(notification.TelegramID, translation.NotFound)
}
default:
continue
}
}
кроме того есть цикл for без условий для постоянной работы в фоне и возможности вводить простые команды вроде quit, statistics и подобных.
Ну и занимает это всё добро 102 процента vps'ного cpu постоянно. При запуске на рабочем компьютере (4 ядра) занимает 30%.
С этим что-то можно сделать кроме выставления таймингов (time.Sleep()) внутри каждого цикла?
Ответы (1 шт):
У вас select не блокируется из-за default: continue
Всякий раз, когда программа проверяет наличие уведомления в канале, срабатывает select: если в канале что-то есть, то запускается обработчик, а если нет, то цикл продолжается.
Вам достаточно переписать цикл вот так:
for {
notification = <-botNotification
switch notification.Code {
case 1:
c.SendChatAction(notification.TelegramID, tbot.ActionTyping)
time.Sleep(1 * time.Second)
c.SendMessage(notification.TelegramID, translation.ManagerOpened)
case 2:
c.SendChatAction(notification.TelegramID, tbot.ActionTyping)
time.Sleep(1 * time.Second)
c.SendMessage(notification.TelegramID, translation.AdminOpened)
default:
c.SendChatAction(notification.TelegramID, tbot.ActionTyping)
time.Sleep(1 * time.Second)
c.SendMessage(notification.TelegramID, translation.NotFound)
}
}
Присваивание notification = <-botNotification блокируется до получения уведомления, поэтому цикл будет висеть в ожидании уведомления в канале и перестанет тратить CPU.
Если же вам по какой-то причине важно, чтобы цикл временами разблокировался, тогда нужно вместо default поставить таймаут:
select {
case notification := <-botNotification:
switch notification.Code {
case 1:
c.SendChatAction(notification.TelegramID, tbot.ActionTyping)
time.Sleep(1 * time.Second)
c.SendMessage(notification.TelegramID, translation.ManagerOpened)
case 2:
c.SendChatAction(notification.TelegramID, tbot.ActionTyping)
time.Sleep(1 * time.Second)
c.SendMessage(notification.TelegramID, translation.AdminOpened)
default:
c.SendChatAction(notification.TelegramID, tbot.ActionTyping)
time.Sleep(1 * time.Second)
c.SendMessage(notification.TelegramID, translation.NotFound)
}
case <-time.After(10*time.Second):
fmt.Println("10 seconds of inactivity")
continue
}