C # et StreamWriter problème de gestion de la mémoire StreamReader, pourquoi ne deallocate mémoire utilisée?

StackOverflow https://stackoverflow.com/questions/3095030

Question

Je suis sur un StreamReader qui utilise un MemoryStream pour écrire à un StreamWriter et à l'intérieur de cette application, mais les augmentations d'utilisation de la mémoire par 300mb (De l'une des entrées plus grandes) et ne pas liberer après Im fait l'utiliser:

StreamWriter log = new StreamWriter("tempFile.txt");
log.Write(reader.ReadToEnd());
log.Close();

reader.DiscardBufferedData();
reader.Close();
reader.Dispose();
memoryStream.Dispose();
log.Dispose();
GC.Collect();

Avant cela et juste après que je reçois l'utilisation de la RAM et avant qu'il ne soit 300 mb moins après mais je ne sais pas pourquoi. J'ai fait tout ce que je peux penser à libérer cette mémoire étant donné que la seule chose qui se passe ici est les données du lecteur est placé dans le fichier texte que je ne vois pas pourquoi une grande quantité de mémoire serait même nécessaire d'utiliser temporairement. Y at-il quelque chose que je suis absent? ... Merci.

Était-ce utile?

La solution

Vous cherchez à la RAM utilisée par le processus lui-même? Je n'attendre à ce que de descendre. Le processus se bloque sur la mémoire et le réutiliser pour d'autres affectations. Il ne remet pas au système d'exploitation. C'est juste le .NET tend ainsi au travail.

peut obtenir potentiellement à jeter la mémoire avec un certain appel API CLR -. Mais le plus souvent je ne voudrais pas

Cela ne signifie pas que la mémoire a vraiment une fuite - il est encore utilisable par le même processus. Par exemple, si vous avez effectué la même action à nouveau, il ne serait probablement pas nécessaire d'augmenter la taille du tas - vous verriez l'appartement de séjour d'utilisation de la mémoire au niveau du processus. Utilisez le CLR perfmon graphiques pour voir la mémoire utilisée dans le tas managé pour voir s'il y a un véritable fuite.

(Il y a aussi des mesures différentes de la quantité de mémoire une application utilise réellement. Lequel est intéressant dépend de ce que vous essayez de le faire.)

EDIT: Si l'extrait de code est indicatif véritablement du code que vous utilisez, puis il y a une alternative beaucoup plus simple. Flux des données

using (TextWriter writer = File.CreateText("tempFile.txt"))
{
    CopyText(reader, writer);
}

static void CopyText(TextReader reader, TextWriter writer)
{
    char[] buffer = new char[8192];
    int charsRead;
    while ((charsRead = reader.Read(buffer, 0, buffer.Length)) > 0)
    {
        writer.Write(buffer, 0, charsRead);
    }
}

Notez que si vous changez réellement l'encodage, vous pouvez le faire sans utiliser une paire TextWriter / TextReader pour commencer.

De cette façon, vous aurez pas besoin d'avoir toute la chaîne en mémoire ainsi que sa représentation binaire (dans le MemoryStream). Vous aurez encore la représentation binaire bien sûr - ne vous Vous pour tout écriture dans le MemoryStream à commencer par

Autres conseils

En plus de ce que Jon a affiché, la façon dont l'environnement d'exécution .NET se comporte vous donne acutally une importante avantages - garder la mémoire allouée pour le processus est une bonne chose à moins que le système est faible sur la mémoire ( dans ce cas, le moteur d'exécution serait probablement relâcher).

Par exemple, si vous avez souvent besoin d'allouer beaucoup de mémoire (comme dans la méthode que vous avez publié ici), il est plus efficace si le processus a déjà la mémoire allouée (même si elle ne sert pas à stocker tout. objets NET). Lorsque vous Runt il méthode la prochaine fois, l'allocation sera beaucoup plus rapide!

Quoi qu'il en soit, quelques choses que vous pourriez faire sont:

  • Vous pouvez essayer d'exécuter une autre application intensive de mémoire pour voir si l'environnement d'exécution libère la mémoire lorsque le système a besoin
  • Vous pouvez utiliser un profileur .NET pour voir s'il y a des objets vivants que vous attendez à recueillir après l'exécution de la méthode

Je ne sais pas si ça va aider, mais essayer une portée de using:

using (StreamReader reader = new StreamReader(somestream))
using (StreamWriter log = new StreamWriter("tempFile.txt"))
{
    log.Write(reader.ReadToEnd());
}

Dans le segment mentionné ci-dessus, tous log, reader et memoryStream sont encore en portée et ne peut donc pas être les déchets ramassés. Je ne sais pas ce que l'implmentation de Dispose sur ces objets est, mais il est tout à fait probable qu'ils en maintenant une grande partie des données en mémoire même après Dispose est appelée (car Dispose généralement ne se ferme que handles de fichiers, la mémoire non géré, et ce, et ne supprime pas nécessairement des tampons internes). Si vous voulez que cela fonctionne comme prévu, vous devez laisser tous les objets référencés hors de portée et deviennent déréférencées.

Vraiment, cependant, ne vous inquiétez pas à ce sujet à moins que l'utilisation de la mémoire est vous causer de la douleur explicite.

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