Ограничение использования оперативной памяти. (C# .NET)

Есть огромные файлы около 100Мб. Я хочу загрузить их в память (RAM), обработать и сохранить где-нибудь.

В то же время я хочу, чтобы был лимит использования памяти. Например, 100Mb, для моего приложения не используйте больше, чем этот предел памяти. Если лимит превышен, файл обрабатывается частями.

Мое понимание этого:

var line = file.ReadLine();
var allowed = true;

while( allowed && line != null ) 
{
   var newObject = new SomeObject( line );
   list.add( newObject );

   // Checking the memory
   allowed = CheckUsedMemory(); 

   line = file.ReadLine()
} 

Как ограничить использование оперативной памяти? Как реализовать метод CheckUsedMemory? Спасибо.

UPD

Спасибо всем за хорошие советы.

5 ответов

Решение

Во-первых, спасибо, что знаете о вашем потреблении памяти. Если бы только больше программистов были такими внимательными...

Во-вторых, я бы не стал беспокоиться: возможно, пользователь хочет, чтобы ваше приложение работало как можно быстрее, и готов сжечь 8000 мегабайт памяти, чтобы получить результаты на 5% быстрее. Позволь им.:)

Но искусственное ограничение объема памяти, занимаемой вашим приложением, может значительно увеличить время обработки, если в этом процессе вы получите больший доступ к диску. Если кто-то работает в системе с ограниченным объемом памяти, он может уже иметь дисковый трафик для подкачки - если вы искусственно сбрасываете память до того, как закончите с ней, вы только вносите дополнительный вклад в дисковый ввод-вывод, входя в систему. способ обмена. Пусть ОС справится с этой ситуацией.

И наконец, шаблон доступа, который вы здесь написали (последовательный, построчный), очень распространен, и, несомненно, разработчики.NET приложили огромные усилия, чтобы довести использование памяти из этого шаблона до минимума. Добавление объектов в ваши внутренние деревья по частям - хорошая идея, но очень немногие приложения могут извлечь из этого пользу. (Сортировка слиянием - это отличное приложение, которое значительно выигрывает от частичной обработки.)

В зависимости от того, что вы делаете со своим законченным списком объектов, вы не сможете улучшить работу сразу со всем списком. ИЛИ, вы могли бы извлечь большую выгоду из разрыва его на части. (Если Map Reduce хорошо описывает вашу проблему с обработкой данных, то, возможно, вы выиграете, если разберетесь с ней.)

В любом случае, я бы немного опасался использовать "память" в качестве эталона для принятия решения о том, когда разделять обработку: я бы предпочел использовать "1000 строк ввода", "десять уровней вложенности" или "запускать станки". в течение пяти минут "или что-то, что основано на вводе, а не вторичном эффекте потребляемой памяти.

Вы можете попробовать с:

long usedMemory = GC.GetTotalMemory(true);

или же

long usedMemory = GC.GetTotalMemory(false);

Первая заставит сборщик мусора (очистку) памяти, поэтому он медленнее (миллисекунды)

Затем прочитайте это, чтобы увидеть, сколько памяти имеет ваша машина:

Как вы получаете общий объем оперативной памяти компьютера?

Помните, что если вы работаете как 32-битное приложение, вы не можете использовать всю память, и что другие процессы могут использовать память!

Обычная процедура - не загружать все в память, а читать файлы кусками, обрабатывать их и сохранять. Если вам по какой-то причине нужно хранить все в оперативной памяти (скажем, для сортировки), то вам вполне может потребоваться вложить больше оперативной памяти.

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

GC.GetTotalMemory () скажет вам, сколько памяти вы используете.

100 МБ ОЗУ не так много сегодня. Считывание в память, обработка и возврат на диск могут быть выполнены довольно быстро. Помните, что вы не сможете избежать копирования с диска в память и обратно на диск. Использование StringBuilder (не String) для его хранения не обязательно приведет к чрезмерным накладным расходам в приложении. Запись 100 МБ за одну операцию, безусловно, быстрее, чем одна строка за раз.

Похоже, что вы хотите обрабатывать файл построчно, но может быть полезно знать, что в.NET 4 вы можете использовать файлы с отображением в памяти, что позволяет вам редко обращаться к большим файлам

Вы не можете реально ограничить использование памяти. Вы можете ограничить только объем памяти, который вы резервируете. Освобождена ли остальная часть памяти или нет, зависит от сборщика мусора.

Поэтому я бы посоветовал вам интересоваться только количеством строк (или, предпочтительно, количеством символов), которые вы в настоящее время буферизуете, прежде чем обрабатывать их.

В комментариях люди предложили вам читать файл построчно. Это очень хороший совет, если вы можете обрабатывать файл по одной строке за раз. Операционная система все равно будет кэшировать файл, поэтому вы не потеряете производительность.

Другие вопросы по тегам