2010-04-27 2 views
0

У меня есть большие (сотни МБ или более) файлов, которые мне нужны для чтения блоков с использованием C++ в Windows. В настоящее время соответствующими функциями являются:Улучшение производительности чтения файлов (один файл, 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 файла. Некоторые чтения являются согласованными, большинство из них не являются.

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

ответ

3

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

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

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

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

+0

@ Джерри: Похоже, ваше сообщение там отрезало. Я думаю, что он означает «Когерентный» - это последовательный доступ. –

+0

@Billy: yup, случайно попал в клавишу табуляции, когда я намеревался попасть в замок. Часть того, что я сказал, должна применяться, если он означает последовательный. –

2

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

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

Смежные вопросы