Чрезвычайно высокая скорость подкачки активной памяти на диск, но низкое использование постоянной памяти

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

Я разрабатываю программу, которая обрабатывает множество изображений, которые она загружает с жесткого диска. Из каждого изображения он генерирует некоторые данные, которые я сохраняю в списке. Для каждых 3600 изображений я сохраняю список на жесткий диск, его размер составляет примерно от 5 до 10 МБ. Он работает так быстро, как только может, поэтому максимально использует один поток ЦП.

Программа работает, она генерирует данные, которые должна, но когда я анализирую их в Visual Studio, я получаю предупреждение: DA0014: Чрезвычайно высокая скорость подкачки активной памяти на диск.

Потребление памяти программой, согласно Диспетчеру задач, составляет около 50 МБ и кажется стабильным. Когда я запускал программу, у меня оставалось около 2 ГБ из 4 ГБ, поэтому я думаю, что у меня не заканчивается оперативная память. Использование памяти моей программойhttps://i.stack.imgur.com/TDAB0.png

В описании правила DA0014 говорится: «Количество выходных страниц в секунду часто намного превышает, например, количество записей страниц в секунду. Поскольку выходные страницы в секунду также включают измененные страницы данных из кэша системных файлов. Однако это не так. всегда легко определить, какой процесс непосредственно отвечает за пейджинг и почему».

Означает ли это, что я получаю это предупреждение просто потому, что читаю много изображений с жесткого диска, или это что-то другое? Не совсем уверен, какую ошибку я ищу.

РЕДАКТИРОВАТЬ: Ссылка на изображение вставлено.

EDIT1: размер изображений составляет около 300 КБ каждый. Я удаляю каждую перед загрузкой следующей.

ОБНОВЛЕНИЕ: Судя по экспериментам, подкачка происходит просто из-за загрузки большого количества файлов. Поскольку я не являюсь экспертом в C# или базовом API GDI+, я не знаю, какой из ответов является наиболее правильным. Я выбрал ответ Андраса Золтанса, поскольку он был хорошо объяснен и потому, что, кажется, он проделал большую работу, чтобы объяснить причину такому новичку, как я :)


person Anders    schedule 07.12.2012    source источник
comment
Вы можете попробовать отключить файловый кеш и повторить проверку, чтобы увидеть, есть ли разница. technet.microsoft.com/en-us/sysinternals/bb897561   -  person JasonD    schedule 07.12.2012
comment
Может ли быть так, что изображения читаются с использованием файлов с отображением памяти? Если да, то большое количество ошибок страниц является исключительным поведением, потому что именно так изображения читаются эффективно.   -  person Codo    schedule 07.12.2012
comment
@JasonD Пытался установить максимальный размер на что-то очень низкое, но текущий размер просто перерос его. И никаких изменений в производительности программы, но Windows определенно вела себя странно :)   -  person Anders    schedule 07.12.2012
comment
@Codo Насколько мне известно, изображения не отображаются в памяти. Просто обычные изображения, помещенные в папку на жестком диске.   -  person Anders    schedule 07.12.2012
comment
@AndersJørgensen: отображение памяти — это метод чтения и записи файлов, а не файл особого типа. Это можно сделать с любым файлом. Какие функции или библиотеки вы используете для чтения файлов?   -  person Codo    schedule 07.12.2012
comment
@Codo Я использую Emgu (OpenCV для C#). Конструктор класса Image принимает путь для ввода. Вот справочное руководство emgu.com/wiki/files/2.4. .2/document/Index.html (к сожалению, нельзя напрямую ссылаться на конструктор).   -  person Anders    schedule 07.12.2012


Ответы (2)


Обновлено после получения дополнительной информации

Рабочий набор вашего приложения может быть не очень большим, но как насчет размера виртуальной памяти? Пейджинг может происходить из-за этого, а не только из-за его физического размера. См. этот снимок экрана из Process Explorer VS2012, работающего в Windows 8:

Память VS 2012

А в диспетчере задач? По-видимому, частный рабочий набор для того же процесса составляет 305 376 КБ.

Из этого мы можем сделать вывод: а) диспетчеру задач не всегда можно доверять и б) размер приложения в памяти, насколько это касается ОС, гораздо сложнее, чем нам хотелось бы думать.

Возможно, вы захотите взглянуть на это.

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

Затем удалите любую обработку (но сохраните загрузку изображения), которую вы делаете, и снова сравните - обратите внимание на разницу.

Затем полностью заглушите код загрузки изображения — обратите внимание на разницу.

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

Теперь, глядя на Код изображения Emgu.CV, он использует класс Image внутри для получения битов изображения, так что это запускает GDI+ через функцию GdipLoadImageFromFile (вторая запись в этом указателе)), чтобы декодирует изображение (используя системные ресурсы, а также потенциально большие массивы байтов), а затем копирует данные в несжатый массив байтов, содержащий фактические значения RGB.

Этот байтовый массив выделяется с помощью GCHandle.Alloc (также окруженного GC.AddMemoryPressure и GC.RemoveMemoryPressure) для создания закрепленного байтового массива для хранения данных изображения (несжатых). Теперь я не специалист по управлению памятью .Net, но мне кажется, что у нас есть потенциал для фрагментации кучи здесь, даже если каждый файл загружается последовательно, а не параллельно.

Является ли это причиной жесткого пейджинга, я не знаю. Но это кажется вероятным.

В частности, представление изображения в памяти может быть специально ориентировано на отображение, а не на исходные байты файла. Так что если мы говорим, например, о JPEG, то JPEG размером 300 КБ может занимать значительно больше физической памяти, в зависимости от его размера. Например. 32-битное изображение 1027x768 занимает 3 МБ, и оно было выделено дважды для каждого изображения с момента его загрузки (первое выделение), а затем копирования (второе выделение) в объект изображения EMGU перед удалением.

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

person Andras Zoltan    schedule 07.12.2012
comment
Спасибо за вашу помощь. Изображения имеют размер около 300 КБ каждое, и я загружаю их с помощью EMGU (OpenCV для C#), поэтому я не знаю базовой структуры. Но я обращаюсь к пикселям изображения, поэтому байты должны быть каким-то образом доступны. - person Anders; 07.12.2012
comment
@AndersJørgensen обновил - на самом деле у вас нет другого вывода, но есть более подробная информация. - person Andras Zoltan; 07.12.2012
comment
Я попытался удалить код обработки изображений, и кажется, что пейджинг сильно связан с простой загрузкой файлов. Я буду долго думать, нужно ли мне найти исправление или просто купить дополнительный диск для разделения данных и файла подкачки. Спасибо за ответ. - person Anders; 10.12.2012

Однако не всегда легко определить, какой процесс непосредственно отвечает за пейджинг и почему.

Дьявол кроется в этой отговорке. Растровые изображения отображаются в память из файла, содержащего данные пикселей, с помощью файла, отображаемого в памяти. Это эффективный способ избежать чтения и записи данных непосредственно в/из ОЗУ, вы платите только за то, что используете. Механизм, обеспечивающий синхронизацию файла с оперативной памятью, — это пейджинг. Поэтому неизбежно, что если вы обрабатываете много изображений, вы увидите много ошибок на странице. Инструмент, который вы используете, просто недостаточно умен, чтобы знать, что это сделано по замыслу.

Фича, а не баг.

person Hans Passant    schedule 07.12.2012