Проблемы с производительностью при чтении жесткого диска

У меня есть программа на C++, которая читает файлы с жесткого диска и выполняет некоторую обработку данных в файлах. Я использую стандартные API Win32 для чтения файлов. Моя проблема в том, что эта программа несколько раз работает невероятно быстро, а затем внезапно замедляется до 1/6 от предыдущей скорости. Если я читаю одни и те же файлы снова и снова при нескольких запусках, то обычно первый запуск будет самым медленным. Затем он поддерживает скорость, пока я не прочитаю какой-нибудь другой набор файлов. Итак, мое очевидное предположение состояло в том, чтобы профилировать время доступа к диску. Я использовал утилиту perfmon и измерил количество байт чтения ввода-вывода/сек для моей программы. И как и ожидалось была огромная разница (~5 раз) в количестве прочитанных байт. Мои вопросы:

(1). Кэширует ли ОС (в моем случае Windows) недавно прочитанные файлы, чтобы последующие загрузки выполнялись быстрее?

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

Могу ли я что-нибудь сделать для этого?


person Naveen    schedule 29.09.2009    source источник
comment
Не могли бы вы добавить несколько цифр: сколько данных вы читаете (МБ), сколько оперативной памяти доступно и сколько оперативной памяти ваше приложение использует для данных? Вы перезапускаете программу между несколькими запусками или просто освобождаете внутреннюю память?   -  person RED SOFT ADAIR    schedule 30.09.2009
comment
В этом поведении нет ничего удивительного, хотя вам нужно читать большие наборы файлов (или быть очень ограниченным в памяти), чтобы увидеть этот эффект так ясно. Ответ Майкла отвечает на это хорошо.   -  person peterchen    schedule 01.10.2009


Ответы (7)


1) Windows кэширует недавно прочитанные файлы в памяти. Книга Внутреннее устройство Windows содержит прекрасное описание того, как это работает. В современных версиях Windows также используется технология SuperFetch, которая пытается упреждающе извлечь содержимое диска в память на основе истории использования, и ReadyBoost, который может кэшировать на флэш-накопитель, что обеспечивает более быстрый произвольный доступ. Все это увеличит скорость доступа к данным с диска после первоначального запуска.

2) Каталог действительно не влияет на расположение на диске. Дефрагментация вашего диска сгруппирует данные файла вместе. Windows Vista и выше автоматически произведет дефрагментацию вашего диска. В идеале вы хотите выполнять большие последовательные чтения и минимизировать количество операций записи. Небольшие произвольные доступы и чередование операций записи и чтения значительно снижают производительность. Вы можете использовать Windows Performance Toolkit для профилирования доступа к диску.

person Michael    schedule 29.09.2009

Кажется, на ваши пронумерованные вопросы уже есть ответы. Если вам все еще интересно, что вы можете сделать, чтобы улучшить скорость чтения с жесткого диска, вот несколько советов:

  • Если возможно, читайте с помощью функций ОС (например, ReadFile), а не библиотек-оболочек (например, iostreams или stdio). Многие оболочки вводят дополнительные уровни буферизации.
  • Читайте последовательно и сообщите Windows, что вы собираетесь читать последовательно, с помощью флага FILE_FLAG_SEQUENTIAL_SCAN.
  • Если вы собираетесь только читать (а не писать), обязательно откройте файл только для чтения.
  • Читать порциями, а не байтами или символами.
  • В идеале куски должны быть кратны размеру кластера диска.
  • Чтение с диска по смещениям, выровненным по кластеру.
  • Читайте в память на границах страницы. (Если вы выделяете большой кусок, он, вероятно, выровнен по странице.)
  • Расширенный: если вы можете начать свои вычисления после чтения только начала файла, то вы можете использовать перекрывающийся ввод-вывод, чтобы попытаться максимально распараллелить вычисления и последующие чтения.
person Adrian McCarthy    schedule 30.09.2009

Да, Windows (и большинство современных ОС) хранит недавно прочитанные данные файла в неиспользуемой ОЗУ, поэтому, если эти данные файла будут снова запрошены в ближайшем будущем, они уже будут доступны в ОЗУ, и доступа к диску можно избежать.

Что касается ускорения доступа к диску, вы можете попробовать дефрагментировать свой диск, но я не ожидаю, что это слишком сильно поможет. Доступ к диску просто медленный по сравнению с доступом к ОЗУ, поэтому кэширование ОЗУ обеспечивает такое хорошее ускорение.

person Jeremy Friesner    schedule 29.09.2009
comment
Спасибо .. На самом деле я уже дефрагментировал диск. Но без разницы. - person Naveen; 29.09.2009

Можете ли вы в качестве диагностического теста точно измерить время, необходимое для первой загрузки?

Затем возьмите это, чтобы определить скорость передачи. Затем вы можете взять эту скорость передачи и сравнить ее с тем, что вы получаете при запуске HD Tune. Что бы это ни стоило, я запустил это сам и получил минимальную скорость 44,2 МБ/с, среднюю 87 МБ/с, максимальную скорость чтения 110 МБ/с с моим диском Western Digital RE3 (один из самых быстрых доступных дисков SATA со скоростью 7200 об/мин).

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

person Steve Wortham    schedule 29.09.2009
comment
Если вы читаете не так быстро, как при вводе-выводе, попробуйте читать большими порциями, используйте методы асинхронного чтения и рассмотрите возможность использования файлового ввода-вывода с отображением памяти. - person Tom Leys; 30.09.2009

Кроме того, убедитесь, что у вас не заканчивается память во время тестов. Запустите perfmon и отслеживайте «Память» > «Доступные байты» и «Физический диск» > «Чтение диска в байтах/сек» для физического диска, который вы читаете. Мониторинг процесса ввода/вывода также является хорошей идеей. Имейте в виду, что последний объединяет все операции ввода-вывода (включая сеть).

Вы должны ожидать 50 МБ/с для последовательного чтения с одного среднего диска SATA. Пара хороших чередующихся последовательных SCSI-дисков даст вам около 220 МБ/с. Если вы видите, что доступная память приближается к нулю, это будет вашей проблемой. Если он остается ровным после того, как вы сделали первый раунд чтения, значит, это как-то связано с вашим приложением.

person Andre    schedule 30.09.2009

Для дефрагментации одного файла на диск или создать новый нефрагментированный файл.

person Les    schedule 29.09.2009

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

У Tom's Hardware есть обзор того, как это может быть Выполнено.

person Calyth    schedule 30.09.2009