Определение подходящего размера буфера

Я использую ByteBuffer.allocateDirect() для выделения некоторой буферной памяти для чтения файла в память, а затем в конечном итоге хэширует эти байты файлов и получает хэш файл (SHA) из него. Входные файлы имеют большой размер, от нескольких килобайт до нескольких ГБ.

Я прочитал несколько потоков и страниц (даже некоторые из них) относительно выбора размера буфера. Некоторым рекомендуется попытаться выбрать тот, который использует собственная файловая система, чтобы минимизировать шансы операции чтения для частичного блока и т.д. Например, буфер размером 4100 байт и по умолчанию для NTFS - 4096, поэтому дополнительные 4 бита потребуют отдельной операции чтения, что крайне бесполезно.

Так что прилипание с полномочиями 2, 1024, 2048, 4096, 8192 и т.д. Я видел некоторые рекомендуемые буферы размером 32 КБ, а другие рекомендуют делать буфер размером входного файла (возможно, отлично подходит для небольших файлов, но как насчет больших файлов?).

Насколько важно придерживаться встроенных буферов размера блока? В современных условиях (при условии, что современный SATA-диск или лучше, по крайней мере, на 8 Мбайт кэша накопителя и другая современная ОС "магия" для оптимизации ввода-вывода), насколько критичен размер буфера и как лучше всего определить, какой размер для установки моего? Я мог бы статически установить его или динамически определить? Спасибо за понимание.

Ответ 1

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

Как вы говорите, если вы выделите 4100, а фактический размер блока - 4096, вам понадобится два чтения для заполнения буфера. Если вместо этого у вас есть буфер объемом 1 000 000 байт, то для одного блока высокий или низкий значение не имеет значения (поскольку для заполнения этого буфера требуется 245 4096-байтовых блоков). Более того, больший буфер означает, что ОС имеет больше шансов заказать чтение.

Тем не менее, я бы не использовал NIO для этого. Вместо этого я бы использовал простой BufferedInputStream, возможно, 1k-буфер для моих read() s.

Основным преимуществом NIO является сохранение данных из кучи Java. Если вы читаете и записываете файл, например, с помощью InputStream означает, что ОС считывает данные в буфер управления, управляемый JVM, JVM копирует это в буфер на куче, а затем копирует его снова в выключенное -heap buffer, тогда ОС считывает этот буфер с кучей для записи фактических блоков диска (и обычно добавляет свои собственные буферы). В этом случае NIO удалит экземпляры нативной кучи.

Однако, чтобы вычислить хеш, вам нужно иметь данные в куче Java, а Mac SPI переместит его там, Таким образом, вы не получаете преимущества NBI, сохраняя данные с кучи, и IMO "старый IO" легче писать.

Просто не забывайте, что InputStream.read() не гарантированно прочитает все байты, которые вы просите.