какой из них лучше?
сценарий:
горутина для чтения данных некоторых каналов для обработки
go reader1-2()
func reader1() {
for {
select {
case data := <-channel1:
handle(data)
case data2 := <-channel2:
handle(data2)
// without default, if there is no data from two channels, it will hangup to wait IO
}
}
}
func reader2() {
for {
select {
case data := <-channel1:
handle(data)
case data2 := <-channel2:
handle(data2)
default:
time.sleep(1*time.Second)
// with default, if no data from two channels,
// it will sleep 1s or change to 500ms
}
}
}
Что здесь означает «производительность»? Примеры делают разные вещи, а именно, по умолчанию заставляет пользователя постоянно засыпать, когда на каналах нет ожидающих отправок, что кажется бессмысленным в этом сценарии.
@all Я не очень хорошо знаком с принципами голанга и хочу знать, какой из них более эффективен. сценарий только запускает горутину для чтения данных канала. Только хочу знать, что лучше.
Нет абсолютно никаких причин использовать вторую версию. Тур по го описывает, как работают каналы и блокировка.
Если ваша цель - обработать сообщения как можно скорее, то сон без причины вместо ожидания сообщения будет менее эффективным.
@JimB спасибо, он очень похож на мой.
«… И хотите знать, какой из них более эффективен». вы не сказали нам, как вы определяете «эффективность» и «производительность». Я имею в виду, что в первом случае горутина, выполняющая оператор select
, будет так называемой «припаркованной» средой выполнения Go, если ни один из каналов не «готов»; горутина будет помещена обратно в очередь выполнения и в конечном итоге будет выполнена, когда либо каналы (или все) будут готовы. Припаркованная горутина вообще не потребляет циклов процессора; единственная плата за время работы - это парковка и снятие с парковки.
... если вы, в частности, хотели избежать этих затрат на парковку и снятие с парковки, пытаясь реализовать своего рода "занятое ожидание", это не то, как это сделать: вызов time.Sleep
с ненулевым аргументом также припаркует горутину, а затем распаркует ее когда сработает таймер. Вот почему ваш второй пример строго хуже первого: если вы запустите time.Sleep
более одного раза, вы потратите намного больше циклов процессора, чем если бы вы просто ждали каналов.
… Также обратите внимание, что каналы Go не являются просто тупыми: среда выполнения Go знает, как немного раскрутить конкурирующий канал - стараясь не переводить отправляющую / принимающую горутину в спящий режим, когда есть шанс, что канал станет готовым Real Soon Now ™; - Другими словами, пожалуйста, пока не давайте себе преждевременной оптимизации. Сначала сделайте правильный код.
строго говоря, первая версия более эффективна, с более быстрой обработкой. Действительно, он не останавливается на xxSeconds. Вторая версия для меня сильно отличается от первой и в большинстве случаев будет медленнее.
спасибо всем добрые люди, получил от вас знания
В чем смысл зацикливания во втором случае? Всегда будет поздно отвечать, потому что
time.Sleep
всегда будет ждать.