Question

Je 10 fils écrire des milliers de petits tampons (16-30 octets chacun) à un énorme fichier dans des positions aléatoires. Certains des fils jeter OutOfMemoryException sur FileStream.Write () opreation.

Quelle est la cause OutOfMemoryException? Ce qu'il faut rechercher?

J'utilise le FileStream comme celui-ci (pour chaque article écrit - ce code va de 10 différents threads):

using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite, BigBufferSizeInBytes, FileOptions.SequentialScan))
{
 ...
 fs.Write();
}

Je pense que tous les tampons alloués à l'intérieur du FileStream ne sont pas libérés à temps par le GC. Ce que je ne comprends pas pourquoi le CLR, au lieu de lancer, ne fonctionne pas juste un cycle de GC et de libérer tous les tampons inutilisés?

Pas de solution correcte

Autres conseils

Si dix fils sont l'ouverture de fichiers que votre code indique, vous disposez d'un maximum de dix objets FileStream à tout non aliéné le temps. Oui, FileStream fait ont une mémoire tampon interne, dont la taille spécifiée avec « BigBufferSizeInBytes » dans votre code. Pourriez-vous s'il vous plaît indiquer la valeur exacte? Si cela est assez grand (par exemple ~ 100 Mo), il pourrait alors bien être la source du problème.

Par défaut (à savoir lorsque vous ne spécifiez pas de numéro sur la construction), ce tampon est 4kB et qui est généralement très bien pour la plupart des applications. En général, si vous tenez vraiment à la performance d'écriture sur disque, alors vous pourriez augmenter celui-ci à un couple de 100 Ko, mais pas plus.

Cependant, pour votre application spécifique faisant serait pas beaucoup de sens, comme le tampon ne contient jamais plus que les 16-30 octets que vous écrivez dans avant de Dispose () l'objet FileStream.

Pour répondre à votre question, un OutOfMemoryException est jeté uniquement lorsque la mémoire demandée ne peut être attribué après GC a couru. Encore une fois, si le tampon est vraiment grand, le système pourrait avoir beaucoup de mémoire gauche, mais pas contiguë Bouchées. En effet, le tas d'objets volumineux est jamais compactée.

Je l'ai rappelé aux gens à propos de celui-ci à quelques reprises, mais le (Spooky Dooky) .

Votre tampon auquel vous êtes en train de lire peut aussi être le problème (encore une fois un grand tas d'objets liés) également à nouveau, vous devez mettre plus de détails sur ce qui se passe là-bas dans la boucle. Je viens cloue le dernier bug que j'avais qui est pratiquement identique (je joue beaucoup la mise à jour de hachage parallèle de ce qui nécessite un Etat indépendant soit maintenu à travers lecture du fichier de d'entrée) ....

POO! juste et remarqué sur défiler « BigBufferSizeInBytes », je suis penchée vers Grand objet Heap nouveau ...

Je fournirais une petite expédition « mbuf », où vous avez copié dans et hors lieu de permettre à tous de votre fil disperate de lire individuellement à travers Si je vous étais, (ce qui est extrêmement difficile en raison de l'absence de contexte), votre large éventail de support ... (il est difficile de ne pas causer des allocations insadential très subtile syntaxe de code).

buffers ne sont généralement pas affectés à l'intérieur du FileStream. Peut-être que le problème est la ligne « écrit des milliers de petits tampons » - voulez-vous dire vraiment? Normalement, vous utilisez à nouveau un tampon beaucoup, beaucoup, plusieurs fois (par exemple sur les différents appels en lecture / écriture).

Aussi - est-ce un seul fichier? Un seul FileStream n'est pas garanti thread-safe ... donc si vous ne faites pas la synchronisation, attendez le chaos.

Il est possible que ces limitations proviennent de l'OS sous-jacent, et que le .NET Framework est impuissante à surmonter ce genre de limitations.

Ce que je ne peux pas déduire de votre exemple de code est de savoir si vous ouvrez un grand nombre de ces objets FileStream en même temps, ou les ouvrir très vite dans l'ordre. Votre utilisation du mot clé « utilisant » fera en sorte que les fichiers sont fermés après l'appel fs.Write (). Il n'y a pas de cycle de GC nécessaire pour fermer le fichier.

La classe FileStream est vraiment orienté vers un accès en lecture / écriture séquentielle des fichiers. Si vous avez besoin d'écrire rapidement à des endroits aléatoires dans un grand fichier, vous pouvez jeter un oeil à l'aide du mappage de fichiers virtuel.

Mise à jour: Il semble que le mappage de fichiers virtuel ne sera pas officiellement pris en charge dans .NET jusqu'à 4.0. Vous pouvez jeter un oeil à des implémentations de tiers pour cette fonctionnalité.

Dave

Je rencontre quelque chose de semblable et je me demandais si jamais vous épinglé la racine de votre problème?

Mon code ne beaucoup de copie entre les fichiers, en passant un bon nombre de mégas entre les différents fichiers d'octets. J'ai remarqué que si l'utilisation de la mémoire du processus reste dans une fourchette raisonnable, l'allocation de mémoire système jaillit trop élevé lors de la copie - beaucoup plus que ce qui est utilisé par mon processus.

J'ai suivi la question jusqu'à l'appel FileStream.Write () - lorsque cette ligne est retirée, l'utilisation de la mémoire semble aller comme prévu. Mon BigBufferSizeInBytes est la valeur par défaut (4K), et je ne vois nulle part où ceux-ci pourraient être la collecte ...

Tout ce que vous découvriez tout en regardant votre problème serait reçu avec gratitude!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top