Операции ввода-вывода на каналах с использованием ByteBuffer — сравнение производительности

#java #performance #bytebuffer #channels

#java #Производительность #ByteBuffer #Каналы

Вопрос:

Я хочу выполнить операцию ввода-вывода на каналах с использованием ByteBuffer . Наконец, я придумал три решения:

 FileChannel inChannel = new FileInputStream("input.txt").getChannel();
FileChannel outChannel = new FileOutputStream("output.txt").getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024 * 1024);
 

Метод 1: использование hasRemaining()

 while (inChannel.read(buf) != -1) {
    buf.flip();    
    while (buf.hasRemaining()) {
        outChannel.write(buf);
    }    
    buf.clear();
}
 

Метод 2: использование compact()

 while (inChannel.read(buf) != -1 || buf.position() > 0) {
    buf.flip();
    outChannel.write(buf);
    buf.compact();
}
 

Метод 3: гибридная модель

 while (inChannel.read(buf) != -1) {
    buf.flip();
    outChannel.write(buf);
    buf.compact();
}
// final flush of pending output
while (buf.hasRemaining())
    outChannel.write(buf);
 

Вопрос в том, какой метод обладает наибольшей производительностью и пропускной способностью?

Комментарии:

1. Это то, что я хочу знать. Есть ли у вас какие-либо выводы по этому поводу? Помимо заданных ответов? vanillajava.blogspot.kr/2011/11 /…

Ответ №1:

Почему вы compact() вообще хотите использовать? — Это может включать многократное копирование большого количества данных.

Ваш 1-й метод — это правильный путь, если у вас нет серьезных оснований для выполнения другого чтения до того, как будут записаны все ранее прочитанные данные.

Да, и, кстати: Если вам нужно только скопировать данные из одного файла в другой, взгляните на transferTo() , или transferFrom() . Это наиболее эффективный способ копирования файлов, поскольку при этом могут использоваться очень эффективные операции базовой ОС, например, DMA.

(Редактировать: transferTo () и т. Д., Конечно, Не нужен никакой ByteBuffer, там смешаны две мысли :))

Ответ №2:

Чтобы максимизировать производительность, я предлагаю вам попробовать прямой буфер размером около 32 КБ. Эти размеры от 16 до 64 КБ часто работают лучше всего в зависимости от вашей системы.

Для файловых каналов он должен иметь возможность читать / записывать все данные каждый раз, поэтому я не думаю, что различные методы будут иметь какое-либо значение. Однако это может иметь значение при чтении / записи в каналы сокетов.

Комментарии:

1. @JinKwon то же самое, да. 😉 И вот google.co.uk/search ? q = Питер Лоури (по крайней мере, на первой странице)