Улучшение производительности чтения файлов (один файл, C ++, Windows) - PullRequest
0 голосов
/ 27 апреля 2010

У меня есть большие (сотни МБ или более) файлы, которые мне нужны для чтения блоков при использовании C ++ в Windows. В настоящее время соответствующие функции:

errorType LargeFile::read( void* data_out, __int64 start_position, __int64 size_bytes ) const
{
 if( !m_open ) {
  // return error
 }
 else {
  seekPosition( start_position );
  DWORD bytes_read;
  BOOL result = ReadFile( m_file, data_out, DWORD( size_bytes ), &bytes_read, NULL );
  if( size_bytes != bytes_read || result != TRUE ) {
   // return error
  }
 }
 // return no error
}

void LargeFile::seekPosition( __int64 position ) const
{
 LARGE_INTEGER target;
 target.QuadPart = LONGLONG( position );
 SetFilePointerEx( m_file, target, NULL, FILE_BEGIN );
}

Производительность вышеописанного не очень хорошая. Чтения находятся на 4K блоков файла. Некоторые чтения являются связными, большинство нет.

Пара вопросов: Есть ли хороший способ профилировать чтения? Какие вещи могут улучшить производительность? Например, будет ли полезным выравнивание данных по секторам? Я относительно плохо знаком с оптимизацией файлового ввода / вывода, поэтому предложения или ссылки на статьи / учебные пособия будут полезны.

Ответы [ 2 ]

4 голосов
/ 27 апреля 2010

Не совсем понятно, что вы подразумеваете здесь под «связным».

В любом случае вы можете начать с рассмотрения того, как вы на самом деле используете данные из файла. Если вы в основном читаете файл в последовательных блоках от начала до конца, вам может быть полезно передать FILE_FLAG_SEQUENTIAL_SCAN при вызове CreateFile. И наоборот, если вы в основном используете один блок из одного места, а затем, скорее всего, , а не , используя другой блок, который (почти) последовательно с этим, вы могли бы выиграть, передав вместо него FILE_FLAG_RANDOM_ACCESS. Если вы достаточно уверены, что после прочтения одного блока данных вы не будете использовать этот же блок данных снова в ближайшее время, вы можете воспользоваться FILE_FLAG_NO_BUFFERING.

Еще одна возможность - просто читать большие куски за раз, если вы можете использовать дополнительные данные. Чтение только 4K за раз может привести к значительным накладным расходам.

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

2 голосов
/ 27 апреля 2010

Производительность вышеописанного не очень хорошая. Чтения находятся на 4K блоков файла. Некоторые чтения являются связными, большинство нет.
Если чтения не согласованы, производительность будет низкой. Возможно, было бы неплохо рассмотреть файлы, отображенные в памяти, или по возможности использовать более согласованные блоки.

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

...