Проблема с производительностью Java ByteBuffer

Хотя при обработке нескольких гигабайтных файлов я заметил кое-что странное: кажется, что чтение из файла с использованием файлового канала в повторно используемый объект ByteBuffer, выделенный с помощью allocateDirect, намного медленнее, чем чтение из MappedByteBuffer, на самом деле это даже медленнее, чем чтение в байтовые массивы используя регулярные вызовы чтения!

Я ожидал, что это будет (почти) так же быстро, как чтение из mappedbytebuffers, поскольку мой ByteBuffer выделяется с помощью allocateDirect, поэтому чтение должно завершаться непосредственно в моем байтовом буфере без каких-либо промежуточных копий.

У меня вопрос: что я делаю не так? Или bytebuffer + filechannel действительно медленнее, чем обычный io / mmap?

В приведенном ниже примере кода я также добавил код, который преобразует считываемые данные в длинные значения, как это постоянно делает мой реальный код. Я ожидал, что метод ByteBuffer getLong () будет намного быстрее, чем мой собственный байтовый shuffeler.

Результаты тестирования: mmap: 3.828 bytebuffer: 55.097 обычный ввод-вывод: 38.175

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.MappedByteBuffer;

class testbb {
    static final int size = 536870904, n = size / 24;

    static public long byteArrayToLong(byte [] in, int offset) {
        return ((((((((long)(in[offset + 0] & 0xff) << 8) | (long)(in[offset + 1] & 0xff)) << 8 | (long)(in[offset + 2] & 0xff)) << 8 | (long)(in[offset + 3] & 0xff)) << 8 | (long)(in[offset + 4] & 0xff)) << 8 | (long)(in[offset + 5] & 0xff)) << 8 | (long)(in[offset + 6] & 0xff)) << 8 | (long)(in[offset + 7] & 0xff);
    }

    public static void main(String [] args) throws IOException {
        long start;
        RandomAccessFile fileHandle;
        FileChannel fileChannel;

        // create file
        fileHandle = new RandomAccessFile("file.dat", "rw");
        byte [] buffer = new byte[24];
        for(int index=0; index<n; index++)
            fileHandle.write(buffer);
        fileChannel = fileHandle.getChannel();

        // mmap()
        MappedByteBuffer mbb = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, size);
        byte [] buffer1 = new byte[24];
        start = System.currentTimeMillis();
        for(int index=0; index<n; index++) {
                mbb.position(index * 24);
                mbb.get(buffer1, 0, 24);
                long dummy1 = byteArrayToLong(buffer1, 0);
                long dummy2 = byteArrayToLong(buffer1, 8);
                long dummy3 = byteArrayToLong(buffer1, 16);
        }
        System.out.println("mmap: " + (System.currentTimeMillis() - start) / 1000.0);

        // bytebuffer
        ByteBuffer buffer2 = ByteBuffer.allocateDirect(24);
        start = System.currentTimeMillis();
        for(int index=0; index<n; index++) {
            buffer2.rewind();
            fileChannel.read(buffer2, index * 24);
            buffer2.rewind();   // need to rewind it to be able to use it
            long dummy1 = buffer2.getLong();
            long dummy2 = buffer2.getLong();
            long dummy3 = buffer2.getLong();
        }
        System.out.println("bytebuffer: " + (System.currentTimeMillis() - start) / 1000.0);

        // regular i/o
        byte [] buffer3 = new byte[24];
        start = System.currentTimeMillis();
        for(int index=0; index<n; index++) {
                fileHandle.seek(index * 24);
                fileHandle.read(buffer3);
                long dummy1 = byteArrayToLong(buffer1, 0);
                long dummy2 = byteArrayToLong(buffer1, 8);
                long dummy3 = byteArrayToLong(buffer1, 16);
        }
        System.out.println("regular i/o: " + (System.currentTimeMillis() - start) / 1000.0);
    }
}

Поскольку загрузка больших разделов и их последующая обработка невозможны (Я буду читать данные повсюду) Думаю, мне следует придерживаться MappedByteBuffer. Спасибо всем за ваши предложения.

16
задан Jonas 27 January 2012 в 02:32
поделиться