Файловый ввод / вывод с потоками - лучший размер буфера памяти - PullRequest
50 голосов
/ 14 июня 2010

Я пишу небольшую библиотеку ввода / вывода, чтобы помочь с большим (хобби) проектом. Часть этой библиотеки выполняет различные функции над файлом, который читается / записывается с помощью объекта FileStream. На каждом StreamReader.Read(...) проходе

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

Мой главный вопрос: какой размер буфера памяти лучше использовать? Думая о расположении физических дисков, я мог бы выбрать 2 КБ, который бы покрывал размер сектора компакт-диска и представлял собой кратное число секторов жесткого диска в 512 байт. Выше дерева абстракции вы можете использовать больший буфер, который мог бы одновременно читать весь кластер FAT. Я понимаю, что с сегодняшними ПК я мог бы выбрать более требовательный к памяти вариант (например, пару МиБ), но затем я увеличиваю время между обновлениями пользовательского интерфейса, и пользователь воспринимает менее отзывчивое приложение.

Кроме того, в конечном итоге я надеюсь предоставить интерфейс, аналогичный файлам, размещенным на серверах FTP / HTTP (через локальную сеть / fastish DSL). Каков будет наилучший размер буфера памяти для них (опять же, «наилучший» компромисс между воспринимаемой отзывчивостью и производительностью)?

Ответы [ 4 ]

71 голосов
/ 14 июня 2010

Файлы уже буферизируются кешем файловой системы.Вам просто нужно выбрать размер буфера, который не заставляет FileStream выполнять собственный вызов Windows ReadFile () API, чтобы заполнить буфер слишком часто.Не опускайтесь ниже килобайта, более 16 КБ - это пустая трата памяти и недружественный к кэшу L1 ЦП (обычно 16 или 32 КБ данных).

4 КБ - этотрадиционный выбор, даже если он будет охватывать страницу виртуальной памяти только случайно.Это трудно профилировать;в итоге вы измерите, сколько времени займет чтение кэшированного файла.Который работает на скорости ОЗУ, 5 гигабайт / сек и выше, если данные доступны в кеше.Он будет в кеше при втором запуске теста, и в производственной среде это случается не так часто.В файловом вводе / выводе полностью доминирует дисковод или NIC , и он медленен, копируя данные арахисом.4 КБ будет работать нормально.

4 голосов
/ 14 июня 2010

Когда я работаю с файлами напрямую через потоковый объект, я обычно использую 4096 байт.Кажется, он достаточно эффективен для нескольких областей ввода / вывода (локальная файловая система, LAN / SMB , сетевой поток и т. Д.), Но я не профилировал это или что-то еще.Когда я видел несколько примеров использования этого размера, он застрял в моей памяти.Это не значит, что он лучший.

3 голосов
/ 14 июня 2010

«Это зависит».

Вам нужно протестировать приложение с разными размерами буфера, чтобы определить, какой из них лучше. Вы не можете угадать заранее.

0 голосов
/ 07 августа 2018

Я полагаю, что значение по умолчанию обычно лучшее - поэтому я использую 4096B на основе internal const int переменной DefaultBufferSize в FileStream class.

...