Файловый ввод / вывод с потоками - лучший размер буфера памяти
Я пишу небольшую библиотеку ввода / вывода, чтобы помочь с большим (хобби) проектом. Часть этой библиотеки выполняет различные функции над файлом, который читается / записывается через FileStream
объект. На каждой StreamReader.Read(...)
проходить,
Я запускаю событие, которое будет использоваться в главном приложении для отображения информации о прогрессе. Обработка, выполняемая в цикле, является бесполезной, но не слишком трудоемкой (например, это может быть простая копия файла или шифрование...).
Мой главный вопрос: какой размер буфера памяти лучше использовать? Думая о расположении физических дисков, я мог бы выбрать 2 КБ, который бы покрывал размер сектора компакт-диска и представлял собой кратное число секторов жесткого диска в 512 байт. Выше дерева абстракции вы можете использовать больший буфер, который мог бы одновременно читать весь кластер FAT. Я понимаю, что с сегодняшними ПК я мог бы выбрать более требовательный к памяти вариант (например, пару МиБ), но затем я увеличиваю время между обновлениями пользовательского интерфейса, и пользователь воспринимает менее отзывчивое приложение.
Кроме того, в конечном итоге я надеюсь предоставить аналогичный интерфейс для файлов, размещенных на FTP / HTTP-серверах (через локальную сеть / fastish DSL). Каков будет наилучший размер буфера памяти для них (опять же, "наилучший" компромисс между воспринимаемой отзывчивостью и производительностью)?
4 ответа
Файлы уже буферизируются кешем файловой системы. Вам просто нужно выбрать размер буфера, который не заставляет FileStream выполнять собственный вызов Windows ReadFile() API, чтобы заполнить буфер слишком часто. Не опускайтесь ниже килобайта, более 16 КБ - пустая трата памяти и недружественная к кэш-памяти L1 ЦП (обычно 16 или 32 КБ данных).
Традиционный выбор - 4 КБ, хотя он и будет занимать страницу виртуальной памяти только случайно. Это трудно профилировать; в итоге вы измерите, сколько времени займет чтение кэшированного файла. Который работает на скорости ОЗУ, 5 гигабайт / сек и выше, если данные доступны в кеше. Он будет в кеше при втором запуске теста, и в производственной среде это случается не так часто. В файловом вводе / выводе полностью доминирует дисковод или сетевая карта, и он медленен, копирование данных происходит из арахиса. 4 кб будет работать нормально.
Когда я работаю с файлами напрямую через потоковый объект, я обычно использую 4096 байт. Кажется, он достаточно эффективен для нескольких областей ввода / вывода (локальная файловая система, LAN / SMB, сетевой поток и т. Д.), Но я не профилировал это или что-то еще. Когда я видел несколько примеров использования этого размера, он застрял в моей памяти. Это не значит, что это лучшее, хотя.
"Это зависит".
Вам нужно протестировать ваше приложение с разными размерами буфера, чтобы определить, какой из них лучше. Вы не можете угадать заранее.
Я полагаю, что значение по умолчанию является лучшим - поэтому я использую 4096B
основанный на internal const int
переменная DefaultBufferSize
в классе FileStream.