Производительность сопоставленных файлов памяти Win32 по сравнению с CRT fopen/fread
Мне нужно читать (сканировать) файл последовательно и обрабатывать его содержимое.
Размер файла может быть от очень маленького (несколько КБ) до очень большого (несколько ГБ).
Я попробовал два метода с использованием VC10/VS2010 на 64-разрядной версии Windows 7:
- Отображаемые файлы памяти Win32 (т.е. CreateFile, CreateFileMapping, MapViewOfFile и т.д.).
- fopen и fread из CRT.
Я думал, что способ отображения файлов с памятью может быть быстрее, чем функции CRT, но некоторые тесты показали, что скорость почти одинакова в обоих случаях.
Для MMF используются следующие операторы С++:
HANDLE hFile = CreateFile(
filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
HANDLE hFileMapping = CreateFileMapping(
hFile,
NULL,
PAGE_READONLY,
0,
0,
NULL
);
Файл читается последовательно, фрагмент куском; каждый кусок SYSTEM_INFO.dwAllocationGranularity
по размеру.
Учитывая, что скорость почти одинакова с MMF и CRT, я бы использовал функции CRT, потому что они более простые и многоплатформенные. Но мне любопытно: правильно ли я использую технику MMF? Нормально ли, что производительность MMF в этом случае файла scannig последовательно совпадает с CRT?
Спасибо.
Ответы
Ответ 1
Я считаю, что вы не увидите большой разницы, если вы последовательно будете обращаться к файлу. Поскольку файловый ввод-вывод очень сильно кэширован, вероятно, также используется + read-ahead.
Все будет по-другому, если у вас было много "переходов" во время обработки файлов. Затем каждый раз, когда установка нового указателя файла и чтение новой части файла, вероятно, будет убивать CRT, тогда как MMF предоставит вам максимально возможную производительность
Ответ 2
Поскольку вы сканируете файл последовательно, я бы не ожидал, что шаблон использования диска будет сильно отличаться для любого метода.
Для больших файлов MMF может уменьшить локальность данных и даже привести к копированию всего или части файла, помещенного в файл подкачки, тогда как обработка через CRT с использованием небольшого буфера будет проходить в ОЗУ. В этом случае MMF, вероятно, будет медленнее. Вы можете смягчить это, только сопоставление в части основного файла за раз, но тогда все становится более сложным без какой-либо вероятной победы над прямым последовательным вводом-выводом.
MMF - это действительно то, как Windows реализует совместную память между процессами, а не способ ускорить обобщенный ввод-вывод файлов. Кэш файлового менеджера в ядре - это то, что вам действительно нужно использовать здесь.
Ответ 3
Я думал, что файл с отображением памяти техника может быть быстрее, чем CRT функции, но некоторые тесты показали, что скорость почти одинакова для обоих случаев.
Вероятно, вы попадаете в кеш файловой системы для своих тестов. Если вы явно не создадите дескрипторы файлов для обхода кеша файловой системы (FILE_FLAG_NO_BUFFERING
при вызове CreateFile
), кэш файловой системы начнет использовать и сохраняет файлы с недавно полученным доступом в памяти.
Существует небольшая разница в скорости чтения файла, находящегося в кеше файловой системы, с включенной буферизацией, поскольку операционная система должна выполнить дополнительную копию, а также служебные данные системного вызова. Но для ваших целей вы, вероятно, должны придерживаться функций файла CRT.
У Gustavo Duarte есть отличная статья о файлах с отображением памяти (с общей перспективы ОС).
Ответ 4
Оба метода в конечном итоге придут на диск i/o, это будет вашим узким местом. Я бы пошел с одним методом, что моя более высокая функциональность уровня больше нравится - если мне нужна потоковая передача, я пойду с файлами, если мне нужны файлы последовательного доступа и фиксированного размера, я бы рассмотрел файлы с отображением памяти.
Или, если у вас есть алгоритм, который работает только с памятью, то файлы с mem-mapped могут быть более легкими.