Allocation de plus de 1 000 Mo de mémoire en processus .NET 32 bits

Je me demande pourquoi je ne suis pas en mesure d’allouer plus de 1 000 Mo de mémoire dans mon processus .NET 32 bits. La mini-application suivante lève une exception OutOfMemoryException après avoir alloué 1 000 Mo. Pourquoi 1 000 Mo, et non pas 1,8 Go? Y at-il un paramètre de processus que je pourrais changer?

static void Main(ssortingng[] args) { ArrayList list = new ArrayList(); int i = 0; while (true) { list.Add(new byte[1024 * 1024 * 10]); // 10 MB i += 10; Console.WriteLine(i); } } 

PS: La collecte des ordures n’aide pas.

Éditer, pour clarifier ce que je veux: j’ai écrit une application serveur qui traite de très grandes quantités de données avant d’écrire dans la firebase database / le disque. Au lieu de créer des fichiers temporaires pour tout, j’ai écrit un cache en mémoire, ce qui rend le tout très rapide. Mais la mémoire est limitée et j’ai donc essayé de connaître les limites. Et je me suis demandé pourquoi mon petit programme de test lançait l’exception OutOfMemoryException après exactement 1 000 Mo.

La limite d’espace d’adressage virtuel d’un processus Win32 est de 1,5 Go (pas tout à fait vrai). De plus, les frameworks .NET limitent le pourcentage de mémoire qu’un processus .NET peut consumr. Machine.config a un élément processModel avec un atsortingbut memoryLimit qui correspond au% de mémoire disponible qu’un processus peut consumr. La valeur par défaut est 60%.

Si la machine sur laquelle vous travaillez est équipée de 2 Go de mémoire ou si vous n’avez pas activé le commutateur / 3GB dans votre fichier Boot.ini, vous obtiendrez environ 1,3 Go de mémoire par processus.

Je ne trouve pas l’article de la Base de connaissances, mais si je me souviens bien, .NET 1.x ne peut pas traiter au-delà de la limite de 1,5 Go (1,8 Go?), Quels que soient vos parameters.

http://blogs.msdn.com/tmarq/archive/2007/06/25/some-history-on-the-asp-net-cache-memory-limits.aspx http://social.msdn.microsoft.com / Forums / fr-fr / clr / thread / c50ea343-b41b-467d-a457-c5a735e4dfff http://www.guidanceshare.com/wiki/ASP.NET_1.1_Performance_Guidelines_-_Caching#Configure_the_Memory_Limit

Avoir d’énormes blocs de mémoire n’est jamais une bonne idée, même en 64 bits. Vous avez de gros problèmes de mémoire contiguë et de fragmentation.

Le problème ici est de trouver un bloc contigu. Vous pouvez essayer d’activer le mode 3 Go (ce qui pourrait l’aider à trouver quelques octets de plus), mais je le déconseille vraiment . Les réponses ici sont:

  • utiliser moins de mémoire
  • utiliser une firebase database / système de fichiers
  • utiliser x64

Vous voudrez peut-être aussi lire le blog d’ Eric Lippert (il semble avoir une entrée de blog pour chaque question .NET commune …)

J’ai récemment effectué un profilage approfondi autour des limites de mémoire dans .NET sur un processus 32 bits. Nous sums tous bombardés par l’idée que nous pouvons allouer jusqu’à 2,4 Go (2 ^ 31) dans une application .NET mais, malheureusement, ce n’est pas vrai :(. Le processus de demande a autant d’espace à utiliser et le système Cependant, .NET lui-même semble avoir sa propre surcharge, ce qui représente environ 600 à 800 Mo d’applications typiques du monde réel qui repoussent les limites de la mémoire. Cela signifie que dès que vous allouez un tableau d’entiers prenant environ 1,4 Go, vous devriez vous attendre à voir une OutOfMemoryException ().

Évidemment, en 64 bits, cette limite survient bien plus tard (discutons dans 5 ans :)), mais la taille générale de tout ce qui est en mémoire augmente également (je trouve que c’est ~ 1,7 à ~ 2 fois) en raison de la taille accrue du mot.

Ce que je sais avec certitude, c’est que l’idée de mémoire virtuelle du système d’exploitation ne vous donne PAS un espace d’allocation pratiquement infini au sein d’un même processus. Ce n’est que là-bas que la totalité des 2,4 Go est adressable à toutes les applications (nombreuses) exécutées en même temps.

J’espère que cette idée aide un peu.

A l’origine, j’ai répondu à quelque chose de ce qui est raconté ici (je suis toujours un nouveau-né, donc je ne sais pas comment je suis censé faire ces liens):

Existe-t-il une limite de mémoire pour un seul processus .NET?

Vous pouvez allouer BEAUCOUP PLUS de mémoire que ~ 2 Go en générant votre application à une architecture 64 bits, ce qui nécessite la création d’une nouvelle configuration de construction dans Visual Studio, et cette version de l’application ne sera exécutée que sur les versions 64 bits de Windows. . Dans .NET, avec l’option de construction par défaut “N’importe quel processeur” pour votre application, je constate que je ne peux allouer que 1,5 Go de mémoire à partir du segment de mémoire (même sur une machine Windows 64 bits). ne fonctionne en mode 32 bits que s’il est construit en mode “Tout processeur”. Mais en compilant une architecture x64, vous pouvez allouer beaucoup, beaucoup plus de mémoire du tas pendant l’exécution de votre application, et j’expliquerai comment créer une construction x64 pour votre application ci-dessous:

Là encore, en utilisant l’option de construction “Tous les processeurs” normale (par défaut) de votre projet .NET, votre application sera TOUJOURS exécutée en mode 32 bits, même sur un système d’exploitation Windows 64 bits. Par conséquent, vous ne pourrez pas allouer plus de 1,5 à 2 Go de mémoire RAM pendant l’exécution de l’application. Pour exécuter votre application .NET en véritable mode 64 bits, vous devez accéder au gestionnaire de configuration de génération, créer un type de construction pour l’architecture x64, puis recomstackr votre programme pour x64 de manière explicite à l’aide de ce type de construction. L’option de mode de construction x64 peut être créée pour votre solution .NET en procédant comme suit:

  1. Dans le volet “Explorateur de solutions” de Visual Studio, cliquez avec le bouton droit de la souris sur l’icône de la solution et choisissez l’option “Gestionnaire de configuration” dans le menu contextuel. Cela ouvrira la boîte de dialog de génération “Configuration Manager” pour le fichier de solution .NET.
  2. Dans la partie supérieure droite de la boîte de dialog de génération “Configuration Manager”, cliquez sur la flèche orientée vers le bas et sélectionnez l’option ““. Cela ouvrira la boîte de dialog “Nouvelle plate-forme de solution”.
  3. Dans la boîte de dialog “Nouvelle plate-forme de solution”, pour l’option “Plate-forme”, choisissez “x64” dans le menu déroulant. Cliquez ensuite sur le bouton “OK” et la nouvelle option de construction x64 sera désormais disponible dans la boîte de dialog Gestionnaire de configuration.
  4. Ensuite, dans la boîte de dialog “Gestionnaire de configuration”, sélectionnez “x 64” dans le menu déroulant “Plate-forme de solution active”. Le cliquer sur le bouton “Fermer”.
  5. Dans le volet “Explorateur de solutions” de Visual Studio, cliquez avec le bouton droit de la souris sur l’icône du projet CS et choisissez l’option “Propriétés” dans le menu contextuel (la dernière option au bas de ce menu). Cela ouvrira la fenêtre des propriétés du projet CS.
  6. Sur le côté gauche de la fenêtre des propriétés du projet CS, cliquez sur l’onglet “Générer” pour afficher les propriétés de construction de votre projet de code. En haut de cette fenêtre, notez que la “Plate-forme” doit maintenant indiquer “x64” (par opposition à l’option “Tout processeur” par défaut). Si le menu déroulant “Plate-forme” n’indique pas “x64”, vous devez le sélectionner maintenant.
  7. Ensuite, construisez simplement votre code et dans le dossier “bin”, vous devriez maintenant avoir un dossier x64 contenant la nouvelle version 64 bits de votre application.

L’utilisation d’une version 64 bits de votre application sur un système d’exploitation Windows 64 bits permettra à votre programme d’allouer bien plus que ~ 2 Go de mémoire, probablement jusqu’à 2 ^ 64 espaces d’adressage (si vous disposez de la RAM et de l’espace disque disponibles). sont les véritables facteurs limitants au moment de la rédaction de cette réponse).

Si vous manquez ENCORE de mémoire dans votre application, vous pouvez également augmenter la taille du fichier de page mémoire Windows. Sous Windows, le fichier d’échange permet au système d’exploitation de déplacer la mémoire de la RAM vers le disque s’il manque d’espace de mémoire RAM. Toutefois, le déplacement de parties de la mémoire RAM vers et depuis le disque représente un coût important en temps, de sorte que les performances de votre application peuvent en souffrir. Quelles que soient les performances, en augmentant la taille de la page, vous pourriez (en théorie) agrandir le fichier de page, car il y a de la place disponible sur le lecteur C: de votre ordinateur Windows. Dans ce cas, votre application pourrait allouer, par exemple, jusqu’à 4 To de mémoire (ou la quantité de mémoire définie pour la taille de votre fichier de page) pendant l’exécution de votre programme. Pour modifier les parameters de fichier de page pour votre ordinateur Windows, procédez comme suit:

  1. Ouvrez la boîte de dialog “Propriétés système” en cliquant avec le bouton droit de la souris sur “Ce PC” et en choisissant “Propriétés” dans le menu contextuel. Cela peut également être accompli dans les versions ultérieures de Windows (Windows 10, Windows Server 2012, etc.) en cliquant sur “Démarrer”> “Panneau de configuration”> “Système et sécurité”> “Système”.
  2. Sur le côté gauche de la boîte de dialog “Système”, cliquez sur l’option “Propriétés système avancées”. Cela affichera l’onglet “Avancé” de la boîte de dialog “Propriétés système” héritée pour Windows.
  3. Dans l’onglet “Avancé” de la boîte de dialog “Propriétés système”, cliquez sur le bouton “Paramètres” dans la zone “Performances”. Cela ouvrira la boîte de dialog “Options de performance”.
  4. Dans la boîte de dialog “Options de performance”, cliquez sur l’onglet “Avancé” pour afficher le paramètre de taille actuel du fichier de page mémoire Windows.
  5. Pour augmenter la taille du fichier page, cliquez sur le bouton “Modifier”. La boîte de dialog “Mémoire virtuelle” s’ouvre.
  6. Dans la boîte de dialog “Mémoire virtuelle”, sélectionnez le lecteur “C:”, puis sous “Taille personnalisée”, définissez les tailles “initiale” et “maximale”. Vous pouvez utiliser n’importe quelle taille jusqu’à concurrence de la quantité maximale d’espace libre sur le lecteur C: mais cette modification permettra de réserver cet espace pour le fichier de page sur le disque dur.
  7. Cliquez ensuite sur “OK” dans toutes les boîtes de dialog pour valider les nouveaux parameters. Ensuite, redémarrez votre ordinateur pour vous assurer que toutes les modifications ont été correctement effectuées et que les nouveaux parameters du fichier d’échange fonctionnent.

Quoi qu’il en soit, j’espère que cela aidera les gens à comprendre pourquoi ils peuvent rencontrer ce problème de limitation de mémoire de 1,5 à 2 Go dans une application .NET, même sur une machine Windows 64 bits. Cela peut être une question très déroutante pour les gens et j’espère que mon explication est logique. S’il vous plaît n’hésitez pas à m’envoyer un message avec des questions sur cette réponse si nécessaire.

Je pense que le problème ici est que cette application appenda 10 Mo à chaque boucle qu’elle crée, et la boucle est: “while (true)”, ce qui signifie qu’elle appenda ces 10 Mo jusqu’à ce que l’application soit arrêtée. Donc, si cela fonctionnait pendant 100 boucles, cela aurait ajouté près de 1 Go à la RAM, et je suppose que cela aurait été fait en moins de 30 secondes. Mon point est que vous essayez de 10 mégaoctets de mémoire par boucle, dans une boucle sans fin

Je suis vraiment désolé si je n’ai pas compris votre point mais:

 static void Main(ssortingng[] args) { ArrayList list = new ArrayList(); int i = 0; while (true) { using(byte newBt = new byte[1024 * 1024 * 10]) { list.Add(newBt); // 10 MB i += 10; Console.WriteLine(i); } } } 

Avez-vous essayé la méthode d’utilisation? Et cela pourrait être une question stupide mais pourquoi avez-vous créé une boucle éternelle? O si vous essayez la bande de code, les symboles>.> XD.

Source: http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx