Каковы наилучшие методы интенсивного чтения и записи данных на жестком диске?

Я разрабатываю приложение C++ (работающее в Linux), которое очень интенсивно читает файлы журнала и записывает полученные результаты на диск. Я хотел бы знать, как лучше всего оптимизировать такие приложения:

  • Какие настройки ОС улучшают производительность?
  • Какие шаблоны программирования повышают пропускную способность ввода-вывода?
  • Является ли предварительная обработка данных (преобразование в двоичные файлы, сжатие данных и т. д.) полезной мерой?
  • Помогает ли разбиение/буферизация данных на производительность?
  • О каких аппаратных возможностях следует знать?
  • Какие методы лучше всего подходят для профилирования и измерения производительности в этих приложениях?
  • (выразите здесь беспокойство, которое мне не хватает)

Есть ли хорошее чтение, где я мог бы получить основы этого, чтобы я мог адаптировать существующие ноу-хау к моей проблеме?

Спасибо


person tonicebrian    schedule 25.01.2011    source источник
comment
Держите данные в буферах и пишите как можно меньше, так это медленно.   -  person BlackBear    schedule 25.01.2011


Ответы (5)


Сжатие, безусловно, может сильно помочь, и это намного проще, чем настройка ОС. Ознакомьтесь с поддержкой gzip и bzip2 в Boost.IOStreams библиотека. Однако это сказывается на процессоре.

Измерение таких видов работ начинается с команды time. Если системное время очень велико по сравнению с пользовательским временем, то ваша программа тратит много времени на выполнение системных вызовов. Если время настенных («реальных») часов велико по сравнению с системным и пользовательским временем, это означает ожидание диска или сети. Команда top, показывающая, что загрузка ЦП для программы значительно ниже 100 %, также является признаком узкого места ввода-вывода.

person Fred Foo    schedule 25.01.2011
comment
Мы получаем примерно 3-кратное ускорение, выполняя zcat bigfile.gz | ourprogram против ourprorogram < bigfile . За счет более высокой загрузки ЦП, поскольку zcat выполняет распаковку, наша программа не блокирует ввод-вывод и начальное сжатие больших (10 ГБ) файлов. bzip2 дает нам меньшую производительность, чем zcat — вероятно, из-за того, что распаковка занимает больше времени — но все зависит от того, сколько процессорного времени вы тратите по сравнению с распаковкой. - person nos; 25.01.2011

1) Проверьте размер сектора вашего диска.
2) Убедитесь, что диск дефрагментирован.
3) Считайте данные, которые являются «локальными» для последних операций чтения, которые вы сделали, чтобы улучшить локальность кэша (кэширование выполняется операционная система и многие жесткие диски также имеют встроенный кэш).
4) Непрерывная запись данных.

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

Для лучшей производительности чтения вы можете удвоить чтение буфера. Итак, допустим, вы кэшируете 16K блоков при чтении. Прочитайте первые 16 КБ с диска в блок 1. Инициируйте асинхронное чтение 2-х 16 КБ в блок 2. Начните работу с блоком 1. Когда вы закончите с блоком 1, синхронизируйте чтение блока 2 и начните асинхронное чтение в блок 1 3-й блок 16 КБ в блок 1. Теперь работайте над блоком 2. Когда закончите синхронизировать чтение 3-го блока 16 КБ, инициируйте асинхронное чтение 4-го блока 16 КБ в блок 2 и работайте над блоком 1. Промойте и повторяйте, пока не обработаете все данные.

Как уже говорилось, чем меньше данных вам нужно прочитать, тем меньше времени будет потеряно при чтении с диска, поэтому, возможно, стоит читать сжатые данные и тратить время ЦП на расширение каждого блока при чтении. Равное сжатие блока перед записью сэкономит вам дисковое время. Будет ли это победа или нет, на самом деле будет зависеть от того, насколько интенсивно процессор обрабатывает данные.

Кроме того, если обработка блоков асимметрична (т. е. обработка блока 1 может занять в 3 раза больше времени, чем обработка блока 2), рассмотрите тройную или более буферизацию для операций чтения.

person Goz    schedule 25.01.2011

Получите информацию о томе, который вы будете записывать/читать, и создавайте буферы, соответствующие характеристикам тома. например 10 * размер кластера.

Буферизация очень помогает, так как сводит к минимуму объем записи, которую вам нужно сделать.

person James    schedule 25.01.2011

Как было сказано здесь, вы должны проверить размер блока. Вы делаете это с помощью функций семейства stat. В struct stat эта информация находится в поле st_blksize.

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

person Maciej    schedule 25.01.2011

В Windows используйте CreateFile() с FILE_FLAG_SEQUENTIAL_SCAN и/или FILE_FLAG_NO_BUFFERING, а не fopen() - по крайней мере, для записи это возвращает немедленно, а не ждет, пока данные будут сброшены на диск

person Martin Beckett    schedule 25.01.2011