Оптимальный размер буфера зависит от нескольких факторов: размер блока файловой системы, размер кэша ЦП и задержка кэша.
Большинство файловых систем сконфигурировано для использования блоков размером 4096 или 8192. Теоретически, если вы конфигурируете размер буфера так, что вы читаете на несколько байтов больше, чем дисковый блок, операции с файловой системой могут быть крайне неэффективными ( т. е. если вы сконфигурировали буфер для чтения 4100 байт за раз, каждая операция чтения потребовала бы 2 блока чтения файловой системой). Если блоки уже находятся в кеше, вы платите цену RAM -> L3 / L2 задержка кеша. Если вам не повезло, а блоки еще не находятся в кеше, вы также платите за задержку диска-> ОЗУ.
Вот почему вы видите большинство буферов, размер которых равен степени 2 и обычно больше (или равен) размеру блока диска. Это означает, что одно из ваших потоковых чтений может привести к нескольким дисковым чтениям блоков - но эти чтения всегда будут использовать полный блок - без потраченных чтений.
Теперь, это типично смещено в типичном сценарии потоковой передачи, потому что блок, который читается с диска, все еще будет в памяти, когда вы нажмете следующее чтение (в конце концов, мы делаем последовательные чтения здесь) - так при следующем чтении вы платите цену ОЗУ -> L3 / L2 кеша, но не задержку диска -> ОЗУ. С точки зрения порядка величины задержка диска-> ОЗУ настолько медленная, что значительно перекрывает любую другую задержку, с которой вы можете иметь дело.
Итак, я подозреваю, что если вы запустили тест с разными размерами кэша (сам этого не делал), вы, вероятно, обнаружите большое влияние размера кэша вплоть до размера блока файловой системы. Кроме того, я подозреваю, что все выровняется довольно быстро.
Здесь есть тонна условий и исключений - сложности системы на самом деле довольно ошеломляют (просто получить контроль над передачей в кэш L3 -> L2 невероятно сложно, и она меняется с каждым Тип процессора).
Это приводит к ответу «реального мира»: если ваше приложение на 99%, установите размер кэша на 8192 и продолжайте (еще лучше, выберите инкапсуляцию вместо производительности и используйте BufferedInputStream, чтобы скрыть детали). Если вы находитесь в 1% приложений, которые сильно зависят от пропускной способности диска, разработайте свою реализацию, чтобы вы могли поменять различные стратегии взаимодействия с диском и предоставили ручки и наборы, чтобы позволить вашим пользователям тестировать и оптимизировать (или придумать некоторые самооптимизирующаяся система).