Как определить оптимальный размер буфера при чтении файла?
Изучаю Java по 9-у изданию полного руководства Шилдта и хочу написать программу в качестве проекта для обучения, первый этап это чтение данных. И тут я решил немного углубиться в тему, т.к. данные могут иметь большой объём. В таком случае рекомендуют использовать буферизированные потоки ввода\вывода для уменьшения операций чтения, это понятно, но каким сделать размер буфера? У Шилдта фигурирует число 8192. Поискав в интернете я нашёл как советы использовать это число и не париться, так и определить размер буфера исходя из размера блока файловой системы и размера кэша жёсткого диска. В общем я решил задать свои вопросы здесь: каким же должен быть размер буфера, есть ли способы сделать программу переносимой(чтобы производительность операций с диском была одинаково высокой и на других машинах)? Ну и вопрос новичка — что лучше использовать io или nio?
Определить размер кэша и блока из java может быть не так просто (особенно переносимым способом). 8192 хорошее среднее значение. Раньше размер полезных данных в физическом секторе был 512 байт, сейчас 4096. Оба кратны 8192, а то что оно больше будет сглажено ядром и объединением физических секторов в блоки/кластеры. Я бы просто 8192 и использовал.
Универсального числа нет, для каждой ситуации будет свой размер оптимальным. Если тебе важно выжимать последние проценты — делай этот размер конфигурируемым. А так — 4k, 8k, 64k нормальные варианты. Разница будет единицы процентов. Можешь потестировать с помощью dd, параметр bs.
что лучше использовать io или nio?
Для блокирующего — io. Для неблокирующего — nio (а ещё лучше надстройку вроде xnio). Для манипуляций файлами имхо удобней nio и функционала у него больше. Для чтения/записи файлов в 99.999% достаточны именно блокирующие вызовы, если что.
Определить размер кэша и блока из java может быть не так просто (особенно переносимым способом).
А что, в Яве нет stat(2)?
Не помню, давно не писал на ней. Вроде что-то подобное было, но там только размер блока может быть.
Поискал и кажется кое-что добавили в 7-ой версии, но не вижу там размера блока (доки).
Начни лучше с английского и умением пользоваться гуглом. А вот и ответ http://stackoverflow.com/a/10698421/3089918
А вот еще к сведению http://stackoverflow.com/a/237038/3089918 А еще лучше изучить методы и реализацию java.nio.file.Files и на базе его примера городить свои читатели, если readAllBytes не устраивает и нужно внедрять собственный хандлер во время чтения.
В противном случае твои читатели будут работать через задницу. Недавно столкнулся с тем, что в Undertow в IOUtils читатели кривые и не умеют правильно читать UTF8 с небольшими вхождениями кирилицы.
А вот, кстати и этот индуский метод из Undertow:
Гуглить я гуглил и кроме той ссылки, что Вы указали, я могу накидать других, одни разделяют эту точку зрения, другие говорят, что надо определять размер блока файловой системы, кэша жёсткого диска и может что-нибудь ещё. Я, собственно, хотел спросить ни помощи в гуглении, а поделиться опытом тех, кто решал подобные задачи, есть ли средства для определения выше указанных параметров в системе, в которой запускается программа, а главное есть ли смысл или при этом можно выиграть только доли процента и достаточно использовать 8192.
А так — 4k, 8k, 64k нормальные варианты. Разница будет единицы процентов.
Производительности? Зато при использовании слишком маленького размера буфера нагрузки на процессор будет на процентов 20 больше.
использовать это число и не париться
Звучит разумно. Физически данные будут вычитываться размером в «read ahead». Можно посмотреть текущее значение в 512-байтных блоках командой blockdev --report , колонка RA. Обычно это около 128К, но может быть и другое (особенно на RAID/LVM)
Т.е. эти 8К это просто размер «окна», при небольших значениях размер этого буфера к скорости считывания имеет довольно условное отношение
а главное есть ли смысл или при этом можно выиграть только доли процента
Люди с действительно быстрыми медиа получают выигрыш в 156..442 процента! Но в coreutils всё ещё определяют оптимум статически: минимум 128 KB.
в coreutils всё ещё определяют оптимум статически: минимум 128 KB.
Где там а) статически и б) минимум 128К?
Если пройти по ссылке, которую я привёл, то можно увидеть:
Под виндой всё работает же :) Метод плох ещё и потому, что использует платформо-зависимую кодировку. А где этот метод вообще используется?
Где там а) статически и б) минимум 128К?
Если код не понятен, разжёвываю по-русски:
ST_BLKSIZE (sb) - константа для всей файловой системы
А, для разных ФС размер буфера таки разный. Это называется статически. Буду знать.
Наибольшая из двух величин называется минимумом. Тоже буду знать
Им конфиг какой-то читается, а мне было лень писать обертку для чтения html файлов и решил заюзать этот метод, не посмотрев в реализацию.
Самый интересный тред с тегом #джава за последнее время.
надо определять размер блока файловой системы, кэша жёсткого диска и может что-нибудь ещё
Ну и? В накиданых ссылках про то и речь. Хочешь получить перформанс достань инфу о железе и подкрути параметры в рантайме. Если же тебе нужно просто конфиги читать или в кеш что-нибудь закинуть, то не один ли хрен, если ты не гугл или фейсбук?
И вообще, если так придераешься, то кроме собственных экспериментов на разном железе в вопросе не разобраться.