Pourquoi la taille de la pile en C# exactement 1 MO?
Les Ordinateurs d'aujourd'hui ont une grande quantité de RAM physique, mais encore, la taille de la pile de C# est à seulement 1 MO pour les processus 32 bits et 4 MO pour les processus 64 bits (Capacité d'empilage en C#).
Pourquoi la taille de la pile dans le CLR est toujours aussi limité?
Et pourquoi est-il exactement de 1 MO (4 MO) (et pas 2 MO ou 512 KO)? Pourquoi il a été décidé d'utiliser ces montants?
Je suis intéressé par considérations et les raisons derrière cette décision.
- Par défaut la taille de la pile pour 64bit processus de 4MB, il est de 1 mo pour les 32 bits de processus. Vous pouvez modifier la taille de la pile des threads en modifiant la valeur dans son en-tête PE. Vous pouvez également spécifier la taille de la pile en utilisant le droit de surcharge de la
Thread
constructeur. MAIS, cela pose la question, pourquoi avez-vous besoin d'une plus grande pile? - Merci, édité. 🙂 La question n'est pas sur la façon d'utiliser la plus grande taille de la pile, mais pourquoi la taille de la pile est décidé à 1 MO (4 MO).
- Parce que chaque thread va obtenir cette taille de pile par défaut, et la plupart des threads n'avez pas besoin de beaucoup plus. J'ai juste démarré mon PC et le système fonctionne actuellement, 1200 fils. Maintenant, faites le calcul 😉
- Non seulement cela, il doit être contagieuse dans la mémoire. Remarque plus la taille de la pile, moins de threads de votre processus peut créer dans son espace d'adressage virtuel.
Vous devez vous connecter pour publier un commentaire.
Vous êtes à la recherche du mec qui a fait ce choix. David Cutler et son équipe ont choisi un mégaoctet que la taille de pile par défaut. Rien à voir avec .NET ou C#, ce qui a été cloué vers le bas quand ils ont créé de Windows NT. Un mégaoctet est ce qu'il choisit lors de l'EXE en-tête d'un programme ou l'CreateThread() winapi d'appel de ne pas spécifier la taille de la pile de manière explicite. Qui est la façon normale, presque n'importe quel programmeur, il laisse l'OS pour choisir la taille.
Qu'un choix sans doute antérieur à Windows NT design, l'histoire est trop glauque à ce sujet. Ce serait bien si Cutler serait d'écrire un livre sur le sujet, mais il n'a jamais été un écrivain. Il a été extrêmement influent sur la façon dont les ordinateurs fonctionnent. Son premier OS de la conception a été RSX-11M, un système d'exploitation 16 bits pour DEC ordinateurs (Digital equipment Corporation). Fortement influencé Gary Kildall du CP/M, le premier décent OS 8-bit des microprocesseurs. Qui fortement influencé MS-DOS.
Son prochain design a été VMS, un système d'exploitation pour les processeurs 32 bits avec mémoire virtuelle de soutien. Très réussie. Son prochain a été annulé par l'DÉC à travers le temps, la société a commencé la désintégration, de ne pas être en mesure de rivaliser avec le à bas prix sur le matériel PC. Repère de Microsoft, ils ont fait de lui une offre qu'il ne pouvait pas refuser. Beaucoup de ses co-travailleurs ont rejoint trop. Ils ont travaillé sur les machines virtuelles v2, mieux connu sous le nom de Windows NT. DEC énervé à ce sujet, l'argent a changé de mains pour le régler. Si VMS déjà pris un mégaoctet est quelque chose que je ne sais pas, je ne connais que le RSX-11 assez bien. Il n'est pas improbable.
Assez de l'histoire. Un mégaoctet est un beaucoup, un véritable fil conducteur consomme rarement plus de quelques poignées de kilo-octets. Ainsi, un mégaoctet est en fait plutôt un gaspillage. Toutefois, c'est le type de déchets que vous pouvez vous permettre sur une demande de mémoire virtuelle paginée système d'exploitation, qui mégaoctet est juste de la mémoire virtuelle. Des chiffres pour le processeur, un pour chaque 4096 octets. Vous n'avez jamais réellement l'utilisation de la mémoire physique, la mémoire vive de la machine, jusqu'à ce que vous fait face.
Elle est extra excessive dans un .NET programme parce que l'un mégaoctet de taille a été initialement choisi pour accueillir les programmes destinés aux autochtones. Qui ont tendance à créer de grandes pile d'images, stocker des chaînes de caractères et les tampons (tableaux) sur la pile ainsi. Tristement célèbre pour être l'un des logiciels malveillants vecteur d'attaque, un débordement de mémoire tampon peut manipuler le programme avec des données. Pas de la manière .NET des programmes de travail, les chaînes et les tableaux sont alloués sur le tas GC et l'indexation est activée. La seule façon d'allouer de l'espace sur la pile avec le C# est avec le dangereux stackalloc mot-clé.
Le seul non-trivial d'utilisation de la pile dans .NET est par la gigue. Il utilise la pile de votre fil de just-in-time compiler MSIL en code machine. Je n'ai jamais vu ou vérifier la quantité d'espace qu'il nécessite, en fait cela dépend de la nature du code, et si oui ou non l'optimiseur est activé, mais à quelques dizaines de kilo-octets est grosso modo. Qui, autrement, comment ce site a obtenu son nom, un débordement de pile dans un .NET programme est tout à fait mortel. Il n'y a pas assez d'espace à gauche (à moins de 3 kilo-octets) pour encore fiable JIT tout code qui tente d'intercepter l'exception. Kaboom de bureau est la seule option.
Dernier mais non le moins, une .NET programme fait quelque chose d'assez improductif avec la pile. Le CLR commettre la pile d'un thread. C'est cher un mot qui veut dire qu'il n'est pas juste de la réserve de la taille de la pile, il fait également en sorte que l'espace est réservé dans le système d'exploitation du fichier d'échange de sorte que la pile peut toujours être remplacées si nécessaire. À défaut de commettre une erreur fatale et met fin à un programme sans condition. Que se passe uniquement sur la machine, avec très peu de RAM qui tourne beaucoup trop de processus, une telle machine sera tourné à la mélasse avant les programmes commencent à mourir. Un problème possible+ de 15 ans, pas aujourd'hui. Les programmeurs qui accordent leur programme pour agir comme une course de F1 la voiture, le
<disableCommitThreadStack>
élément dans leur .fichier de configuration.Fwiw, Cutler n'a pas cesser de concevoir des systèmes d'exploitation. Cette photo a été faite alors qu'il travaillait sur Azure.
Mise à jour, j'ai remarqué que .NET ne s'engage plus dans la pile. Pas exactement quand ni pourquoi c'est arrivé, ça fait trop longtemps depuis que j'ai vérifié. Je suppose que ce changement de conception s'est passé quelque part autour de .NET 4.5. Assez sensible au changement.
The only way to allocate space on the stack with C# is with the unsafe stackalloc keyword.
- Sont des variables locales, par exemple, uneint
déclarée à l'intérieur d'une méthode qui n'est pas stocké sur la pile? Je pense qu'ils sont.maxStackSize
d'un thread? Je ne pouvais pas le trouver sur [MSDN] (msdn.microsoft.com/en-us/library/5cykbwz4(v=vs. 110).aspx). En fonction de vos commentaires, il semble que l'utilisation des piles sont un minimum absolu, et je peux utiliser la valeur la plus petite pour accueillir le maximum possible de threads. Merci.int
local vars + args, dans un 4 MO de pile: programme:4*1024*1024 / (4*20) = 52429
- donc, pour cette fonction, il peut aller 52,429 niveaux de profondeur sans débordement de la pile. Mon calcul est proche de la vérité?La valeur par défaut réservés taille de la pile est spécifié par l'éditeur de liens et elle peut être remplacée par des développeurs via la modification de la PE de la valeur au moment de la liaison ou pour une personne thread en spécifiant le
dwStackSize
paramètre pour laCreateThread
WinAPI fonction.Si vous créez un thread avec la pile initiale de taille supérieure ou égale à la taille de pile par défaut puis il arrondi au plus proche multiple de 1 MO.
Pourquoi la valeur est égale à 1 MO pour les processus 32 bits et 4 MO pour la version 64 bits? Je pense que vous devriez demander aux développeurs, qui a conçu Windows, ou d'attendre que quelqu'un d'entre eux répond à votre question.
Probablement Mark Russinovich le sait et vous pouvez contact lui. Peut-être que vous pouvez trouver cette information dans son Windows Internals livres plus tôt que la sixième édition qui décrit moins d'infos sur les piles, plutôt que de son l'article. Ou peut-être Raymond Chen sait raisons depuis, il a écrit des choses intéressantes sur Windows internals et de son histoire. Il peut répondre à votre question, mais vous devriez poster une suggestion à l' La Boîte À Suggestion.
Mais en ce moment je vais essayer d'expliquer certaines des raisons probables pour lesquelles Microsoft ont choisi ces valeurs à l'aide de MSDN, Marc et Raymond blogs.
Les valeurs par défaut ces valeurs probablement parce que, dans les premiers temps, les Ordinateurs ont été lents et l'allocation de mémoire sur la pile a été beaucoup plus rapide que l'allocation de mémoire dans le tas. Et depuis pile allocations sont beaucoup moins cher qu'ils ont été utilisés, mais il nécessite une plus grande taille de la pile.
De sorte que la valeur optimale de réservé la taille de la pile pour la plupart des applications. C'est optimal car permet de faire beaucoup d'appels imbriqués et allouer de la mémoire sur la pile de traverser les structures de l'appel de fonctions. En même temps, il permet de créer un grand nombre de threads.
Aujourd'hui, ces valeurs sont principalement utilisés pour des raisons de compatibilité ascendante, parce que les structures qui sont passés en paramètres à WinAPI fonctions sont toujours allouées sur la pile. Mais si vous n'utilisez pas de pile allocations ensuite la pile d'un thread d'utilisation sera sensiblement inférieur à la valeur par défaut de 1 MO et il est inutile de Hans Passant mentionné. Et pour éviter cela, l'OS s'engage uniquement la première page de la pile (4 KO), si d'autres n'est pas spécifié dans l'en-tête PE de l'application. D'autres pages sont allouées sur demande.
Certaines applications remplacent réservés espace d'adressage et d'abord engagé à optimiser l'utilisation de la mémoire. Par exemple, le maximum de la taille de la pile d'un IIS processus natif du fil est de 256 KO (KB932909). Et cette diminution de la valeur par défaut est recommandé par Microsoft:
Sources: