Des centaines de milliers, selon la FAQ Go : Pourquoi les goroutines au lieu des threads?:
Il est pratique de créer des centaines de milliers de goroutines dans le même espace d'adressage.
Le test test/chan/goroutines.go crée 10 000 et pourrait facilement en faire plus, mais est conçu pour s'exécuter rapidement ; vous pouvez changer le nombre sur votre système pour expérimenter. Vous pouvez facilement exécuter des millions, en fonction de la mémoire disponible, comme sur un serveur.
Pour comprendre le nombre maximal de goroutines, notez que le coût par goroutine est principalement la pile. Selon la FAQ encore une fois :
…les goroutines peuvent être très bon marché : elles n'ont que peu de frais généraux en dehors de la mémoire pour la pile, qui ne fait que quelques kilooctets.
Un calcul approximatif consiste à supposer qu'une goroutine a une page de 4 Kio allouée pour la pile (4 Kio est une taille assez uniforme), plus certains petits frais généraux pour un bloc de contrôle (comme un Bloc de Contrôle de Thread) pour le runtime ; cela correspond à ce que vous avez observé (en 2011, avant Go 1.0). Ainsi, 100 Ki routines prendraient environ 400 MiB de mémoire, et 1 Mi routines prendraient environ 4 GiB de mémoire, ce qui est toujours gérable sur un ordinateur de bureau, un peu trop pour un téléphone, et très gérable sur un serveur. En pratique, la taille de la pile de départ varie de la demi-page (2 KiB) à deux pages (8 KiB), donc c'est approximativement correct.
La taille de la pile de départ a changé avec le temps ; elle a commencé à 4 KiB (une page), puis elle a été portée à 8 KiB (2 pages) dans 1.2, puis diminuée à 2 KiB (demi-page) dans 1.4. Ces changements étaient dus à des piles segmentées provoquant des problèmes de performance lors de basculements rapides entre les segments ("hot stack split"), augmentées pour atténuer (1.2), puis diminuées lorsque les piles segmentées ont été remplacées par des piles contiguës (1.4) :
Notes de publication de Go 1.2 : Taille de la pile:
Dans Go 1.2, la taille minimale de la pile lorsqu'une goroutine est créée est passée de 4k à 8k.
Notes de publication de Go 1.4 : Changements dans le runtime:
la taille de départ par défaut pour la pile d'une goroutine en 1.4 a été réduite de 8192 octets à 2048 octets.
La mémoire par goroutine est principalement la pile, et elle commence bas et augmente afin que vous puissiez avoir beaucoup de goroutines à moindre coût. Vous pourriez utiliser une pile de départ plus petite, mais alors elle devrait croître plus tôt (gagner de l'espace au détriment du temps), et les avantages diminuent en raison du bloc de contrôle qui ne rétrécit pas. Il est possible d'éliminer la pile, du moins lorsqu'elle est échangée (par exemple, faire toute l'allocation sur le tas, ou sauvegarder la pile sur le tas lors d'un changement de contexte), mais cela nuit aux performances et ajoute de la complexité. C'est possible (comme dans Erlang), et cela signifie que vous auriez juste besoin du bloc de contrôle et du contexte sauvegardé, permettant un facteur supplémentaire de 5×–10× dans le nombre de goroutines, limité maintenant par la taille du bloc de contrôle et la taille sur le tas des variables locales de la goroutine. Cependant, cela n'est pas très utile, sauf si vous avez besoin de millions de petites goroutines en sommeil.
Comme l'utilisation principale de nombreuses goroutines est pour les tâches liées à l'IO (concrètement pour traiter les appels système bloquants, notamment l'IO réseau ou système de fichiers), vous avez beaucoup plus de chances de rencontrer des limites du système d'exploitation sur d'autres ressources, à savoir les sockets réseau ou les descripteurs de fichiers : golang-nuts › Le nombre maximal de goroutines et de descripteurs de fichiers?. La manière habituelle de traiter cela est avec une piscine de la ressource rare, ou plus simplement en limitant le nombre via un sémaphore; voir Conservation des Descripteurs de Fichiers en Go et Limitation de la Concurrence en Go.