OutOfMemoryException lors du remplissage de MemoryStream: 256 Mo sur un système de 16 Go

J’exécute la méthode suivante sur mon serveur de développement IIS (à partir de VS2010 IDE) sur un ordinateur Windows 7 64 bits avec 16 Go de RAM installée:

public static MemoryStream copyStreamIntoMemoryStream(Stream stream) { long uiLen = stream.Length; byte[] buff = new byte[0x8000]; int nSz; MemoryStream ms = new MemoryStream(); try { while ((nSz = stream.Read(buff, 0, buff.Length)) != 0) { ms.Write(buff, 0, nSz); } } finally { Debug.WriteLine("Alloc size=" + ms.Length); } return ms; } 

et j’obtiens l’ System.OutOfMemoryException sur cette ligne:

 ms.Write(buff, 0, nSz); 

Cela est lancé lorsque 268435456 octets sont alloués:

Alloc taille = 268435456

qui est 0x10000000 ou 256 Mo. Je me demande donc si je dois définir certains parameters globaux pour que cela fonctionne.

Voici une capture d’écran du paramètre de configuration du projet: entrez la description de l'image ici

Réponse courte – le serveur de développement est un processus 32 bits.

Réponse longue pour “pourquoi seulement 256 Mo?”

Tout d’abord, comprenons comment cela fonctionne.

MemoryStream dispose d’un tampon d’octet interne [] pour conserver toutes les données. Il ne peut pas prédire la taille exacte de ce tampon, aussi l’initialise-t-il avec une valeur initiale.

Les propriétés Position et Longueur ne reflètent pas la taille réelle du tampon. Ce sont des valeurs logiques indiquant le nombre d’octets écrits. Elles peuvent facilement être inférieures à la taille réelle du tampon physique.

Lorsque ce tampon interne ne peut pas contenir toutes les données, il doit être “redimensionné”, mais cela signifie créer un nouveau tampon deux fois plus grand que le précédent, puis copier les données d’un ancien tampon dans un nouveau tampon.

Ainsi, si la longueur de votre mémoire tampon est de 256 Mo et que vous avez besoin de nouvelles données à écrire, cela signifie que .Net doit trouver un autre bloc de données de 512 Mo – tout le rest en place, donc heap doit être au moins de 768 Mo sur. l’instant d’allocation de mémoire lorsque vous recevez OutOfMemory.

Notez également que par défaut, aucun object, y compris les tableaux, dans .Net ne peut prendre plus de 2 Go de taille.

Ok, alors voici le morceau échantillon qui simule ce qui se passe:

  byte[] buf = new byte[32768 - 10]; for (; ; ) { long newSize = (long)buf.Length * 2; Console.WriteLine(newSize); if (newSize > int.MaxValue) { Console.WriteLine("Now we reach the max 2Gb per single object, stopping"); break; } var newbuf = new byte[newSize]; Array.Copy(buf, newbuf, buf.Length); buf = newbuf; } 

Si x64 / AnyCPU est intégré et s’exécute depuis la console, tout va bien.

S’il est construit sur x86, il échoue dans la console.

Si vous le mettez par exemple Page_Load, construit en x64 et ouvert à partir du serveur Web VS.Net, cela échoue.

Si vous faites la même chose avec IIS – tout va bien.

J’espère que cela t’aides.

Si vous utilisez le serveur de développement VS par défaut, vous exécutez du code dans un processus x86 / 32 bits. Si vous utilisez des services IIS complets, AppPool est probablement configuré pour fonctionner en mode x86 (mode 32 bits) et dispose donc d’un espace d’adressage très limité (2 Go à moins que vous n’ayez marqué votre application comme prenant en charge les grandes adresses).

Dans le cas d’IIS, assurez-vous que vous avez configuré les sondages d’application pour exécuter x64 (vous ne savez pas quelle est la valeur par défaut). Assurez-vous que votre code cible est défini sur AnyCPU ou x64.

Pour les applications C # autonomes – par défaut, elles sont compilées avec x86 ou AnyCPU / Prefer x86 – définissez la plate-forme cible sur x64.

Pour obtenir un support x64 pour IIS, vous pouvez installer IIS complet ou IIS Express 8.0 (7.5 uniquement fourni avec Windows 7 en 32 bits) à partir de Download IIS 8.0 Express .

Notes de côté:

  • Si vous venez d’installer la version complète d’IIS, veillez à mettre à jour votre solution pour qu’elle utilise IIS pour l’hôte du site.
  • Je n’ai pas d’ordinateur pour vérifier si des étapes supplémentaires doivent utiliser le support x64 pour IIS Express. Consultez cette question – Vous ne pouvez pas obtenir la version bêta d’IIS Express 8 pour exécuter le site Web en tant que processus 64 bits – car cela pourrait vous donner quelques idées.
  • Vous pouvez également essayer de créer votre propre version x64 du serveur de développement en vous basant sur les suggestions présentées ci-dessous: Visual Studio 2010 WebDev WebServer (Cassini) est-il compatible 64 bits?