3

Итак, я использую StreamReader, который использует MemoryStream для записи в StreamWriter и внутри этого приложения, но использование памяти увеличивается на 300 мб (с одного из больших входов) и не освобождается после того, как Im сделал с ним:C# StreamWriter и проблема управления памятью StreamReader, почему память не будет освобождена?

До этого и сразу после получения ОЗУ и до 300 Мб меньше, чем после, но я не знаю почему. Я сделал все, что мог придумать, чтобы выпустить эту память, учитывая, что единственное, что происходит здесь, - это то, что данные от читателя помещаются в текстовый файл, я не понимаю, зачем нужно использовать какой-либо большой объем памяти временно. Есть что-то, чего я не хватает? ... Спасибо.

+0

Я рекомендую использовать профилировщик производительности для вашего приложения. Вы можете обнаружить, что проблемы с производительностью, с которыми вы сталкиваетесь, на самом деле не имеют ничего общего с сообщением об объеме памяти. В зависимости от того, сколько данных вы записываете на диск, вполне вероятно, что больший виновник, влияющий на другие процессы, является соперничеством с дисковыми ресурсами ввода-вывода. Память действительно не должна быть проблемой производительности (насколько влияет на другие процессы), пока вы на самом деле не переполнили физическую RAM и не вызвали значительный пейджинг на диске. –

ответ

6

Вы смотрите на ОЗУ, используемую самим процессом? Я бы не ожидал, что это спустится. Процесс будет зависать в этой памяти и повторно использовать его для дальнейших распределений. Он не возвращает его в операционную систему. Именно так работает .NET.

может потенциально получить его, чтобы выбросить память с помощью какого-либо вызова API CLR, но обычно я этого не делал.

Это не означает, что память действительно просочилась - она ​​по-прежнему может использоваться одним и тем же процессом. Например, если вы повторите одно и то же действие, вероятно, не нужно будет увеличивать размер кучи - вы увидите, что использование памяти остается равным на уровне процесса. Используйте графики perfmon CLR, чтобы увидеть память, используемую в управляемой куче, чтобы увидеть, есть ли утечка подлинных.

(Есть также различные другие меры, сколько памяти приложение на самом деле с помощью которого один Интересно, зависит от того, что вы пытаетесь сделать.).

EDIT: Если фрагмент кода действительно свидетельствует о код, который вы используете, тогда есть гораздо более простая альтернатива: поток данных.

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); 
    } 
} 

Обратите внимание, что если вы не на самом деле изменения кодировки, вы можете сделать это без использования пара TextWriter/TextReader, чтобы начать с.

Таким образом вам не понадобится целая строка в памяти , а также ее двоичное представлениеMemoryStream). Конечно, у вас все равно будет двоичное представление - у вас есть, чтобы написать все в MemoryStream?

+0

Я использую System.Diagnostics.PerformanceCounter() s NextValue(), чтобы получить доступную память, кажется, что использование ОЗУ становится опасно высоким. Это приложение будет выполняться в фоновом режиме, поэтому важно, чтобы он не зависал системные ресурсы, как в настоящее время. –

+0

@ Вы можете попробовать запустить другое приложение, использующее много памяти, и посмотреть, добавляет ли какое-то давление в памяти, чтобы использование спустилось вниз? Потому что это только ресурсы hogging, если это мешает другим приложениям получать память, в которой они нуждаются. –

+0

Понятно, что я попытаюсь это сделать, однако во время работы при использовании других приложений наблюдается заметное замедление при открытии меню запуска Windows. –

0

Я не уверен, если это поможет, но попробовать using область видимости:

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

В дополнение к тому, что писал Джон, то, как ведет себя среда .NET acutally дает вам некоторые важные преимущества - сохранение памяти, выделенной для процесса, является хорошей вещью, если система не является низкой в ​​памяти (в этом случае среда выполнения, вероятно, выпустит ее).

Например, если вам часто приходится выделять много памяти (как в методе, который вы разместили здесь), то это более эффективно, если процесс уже имеет выделенную память (хотя он не используется для хранения каких-либо .NET). Когда вы запустите его метод в следующий раз, распределение будет намного быстрее!

Во всяком случае, несколько вещей, которые вы могли бы сделать это:

  • Вы можете попробовать запустить другую память интенсивного приложение, чтобы увидеть, освобождает ли во время выполнения памяти, когда система нуждается в этом
  • Вы можете использовать некоторые .NET профайлер, чтобы увидеть, есть ли какие-либо живые объекты, которые можно было бы ожидать, чтобы быть собраны после запуска метода
0

в сегменте упомянутых выше, все log, reader и memoryStream все еще находятся в сфере охвата и поэтому не могут собираться мусор. Я не знаю, что имплантирует Dispose на эти объекты, но вполне вероятно, что они все еще хранят большую часть данных в памяти даже после вызова Dispose (поскольку Dispose обычно закрывает только дескрипторы файлов, неуправляемую память и т. и не обязательно удаляет внутренние буферы). Если вы хотите, чтобы это работало так, как ожидалось, вы должны позволить всем ссылочным объектам выйти из области видимости и перестать ссылаться.

Действительно, вам не стоит беспокоиться об этом, если использование памяти не вызывает явной боли.

+0

Кажется, что в определенные моменты времени во время выполнения программ ОС начинает ползать и просто открывать окна и перемещать их вокруг, становится медленной и нерешенной задачей. –

+0

Значения могут быть мусором, собранным сразу после окончательного чтения, когда вы не работаете в отладчике. Вы даже можете записать эту переменную позже, и это не мешает ей раньше быть GC'd. –

+0

@Jon Skeet: Таким образом, все приложение использует около 500 Мб больше оперативной памяти, чем я ожидал бы, это 500 мб для .NET, к которому нужно удержать? Я бы подумал, что существует ограничение на объем буферной памяти, который он поддерживает. –