Существует ли в Go ограничение на максимальное количество горутин?

Ответ

В Go нет жёсткого, встроенного в язык ограничения на количество горутин. Теоретически, их можно создать миллионы. Практический лимит определяется объемом доступной оперативной памяти (RAM).

Ключевые аспекты:

  • Легковесность: Каждая горутина начинается с небольшого стека (около 2 КБ), который может динамически расти и сжиматься по мере необходимости. Это делает их гораздо дешевле системных потоков.
  • Потребление памяти: Несмотря на легковесность, каждая горутина всё же потребляет память. Создание миллионов горутин может потребовать гигабайты RAM, и при исчерпании памяти программа аварийно завершится с ошибкой out of memory.
  • Нагрузка на планировщик: Очень большое количество горутин (миллионы) создает дополнительную нагрузку на планировщик Go, который должен управлять их состоянием, что может незначительно снизить производительность.

Практические рекомендации:

  • Для I/O-bound задач (сетевые запросы, работа с файлами), где горутины часто ожидают, можно и нужно создавать большое их количество (тысячи, десятки тысяч).
  • Для CPU-bound задач (математические вычисления), идеальное количество активных горутин обычно равно количеству ядер процессора (runtime.GOMAXPROCS(0)). Для таких задач часто используют паттерн Worker Pool, чтобы ограничить параллелизм и избежать лишних переключений контекста.

Пример создания миллиона горутин:

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
    numGoroutines := 1_000_000
    for i := 0; i < numGoroutines; i++ {
        go func() {
            time.Sleep(time.Second) // Симуляция работы
        }()
    }
    fmt.Printf("Successfully created %d goroutines.n", numGoroutines)
    fmt.Printf("Current number of goroutines: %dn", runtime.NumGoroutine())
    time.Sleep(2 * time.Second) // Дать время горутинам завершиться
}