Ответ
В Go нет жёсткого, заранее определённого лимита на количество горутин. Однако существуют практические ограничения, которые зависят от ресурсов системы.
Теоретически: Можно создать миллионы горутин. Они очень легковесны, так как начальный размер стека горутины составляет всего около 2 КБ и может динамически расти и сжиматься по мере необходимости.
Практически: Ограничения накладываются:
- Оперативной памятью (RAM): Каждая горутина, даже простаивающая, потребляет память под свой стек. Миллион горутин потребует как минимум 2 ГБ RAM только для стеков.
- Нагрузкой на планировщик (Scheduler): С увеличением числа горутин планировщик Go тратит больше времени на управление ими, что может привести к снижению производительности.
- Процессорным временем (CPU): Горутины выполняются на ограниченном количестве системных потоков (по умолчанию равно количеству ядер CPU, управляется через
GOMAXPROCS
). Слишком большое количество активных горутин приводит к частым переключениям контекста и борьбе за ресурсы CPU.
import (
"fmt"
"runtime"
"time"
)
func main() {
numGoroutines := 1_000_000
for i := 0; i < numGoroutines; i++ {
go func() {
time.Sleep(time.Second * 10) // Просто "висим" в памяти
}()
}
fmt.Printf("Успешно создано %d горутинn", numGoroutines)
fmt.Printf("Текущее количество горутин: %dn", runtime.NumGoroutine())
time.Sleep(time.Second * 12) // Даем время на выполнение
}
Рекомендации
Вместо бесконтрольного создания горутин рекомендуется использовать паттерны для их ограничения, например:
- Пул воркеров (Worker Pool): Заранее создается фиксированное количество горутин-воркеров, которые разбирают задачи из канала.
- Семафор (Semaphore): Использование взвешенного семафора (
golang.org/x/sync/semaphore
) для ограничения одновременного доступа к ресурсу или выполнения кода.