ByteBuffer实现解析 Direct vs Heapped性能比较

来源:互联网 发布:保定软件技术学院 编辑:程序博客网 时间:2024/06/06 18:09

ByteBuffer封装了一个实现类,可以方便的把java基础数据类型(short, int, long, float, double)转换成byte数组形式,反之亦然;做二进制数据的生成和读取时,会特别有用。

实现上,整型数可以通过移位获取各个字节,然后写到byte数组中即可;而浮点型没办法直接获得字节数据,只能通过Float.floatToIntBits(详细参见java api)类似的方法,转换成IEEE 754的二进制表达,变成一个int型,然后再写入byte数组中。读取与此类似。ByteBuffer有两个继承类,HeappedByteBuffer和DirectByteBuffer,api上针对这两种有很详细的描述,我这里说一下实现。

java堆的ByteBuffer

HeappedByteBuffer是通过ByteBuffer.allocate获得的,其内部的byte数组,通过new byte[]获得,所以数据都在java的堆(Heap)中。之后的各种get/put方法都是在操作这个堆上的byte数组,贴两段示例代码:

 ByteBuffer中的getInt方法, 主要处理位置相关,实际的工作在Bits中实现。

 public int ByteBuffer::getInt() {
    return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
    }

Bits中的getInt实现,先拿到4个比特,然后makeInt通过位移构建一个int。

static int Bits::getIntL(ByteBuffer bb, int bi) {
    return makeInt(bb._get(bi + 3),
               bb._get(bi + 2),
               bb._get(bi + 1),
               bb._get(bi + 0));
    }

Bits中的getFloat实现,先调用getInt,然后调用intBitsToFloat把IEEE 754的二进制表达转换为float数。

static float getFloatL(ByteBuffer bb, int bi) {
    return Float.intBitsToFloat(getIntL(bb, bi));
    }

DirectByteBuffer

DirectByteBuffer是通过ByteBuffer.allocateDirect获得的,其内部没有byte数组,只有一个内存地址,这块内存不在java的堆中,而是通过jni直接由jvm提供。其相应的get/put方法都是通过jni操作这个地址。示例代码如下:

 private int getInt(long a) {
    if (unaligned) {
        int x = unsafe.getInt(a);
        return (nativeByteOrder ? x : Bits.swap(x));
    }
    return Bits.getInt(a, bigEndian);
    }

private float getFloat(long a) {
    if (unaligned) {
        int x = unsafe.getInt(a);
        return Float.intBitsToFloat(nativeByteOrder ? x : Bits.swap(x));
    }
    return Bits.getFloat(a, bigEndian);
    }

其中unsafe.getInt是一个jni方法调用。

ByteBuffer还提供一个asIntBuffer类似的调用,返回一个Int视图,这个视图跟ByteBuffer是共享一块后端内存的,所以在视图上做的修改都会反映到ByteBuffer中,反之亦然。通过视图操作,性能上更高一些,因为他提供了批量写入/读取的接口,而且如果ByteBuffer是direct的话,批量操作会被转换为一个jni调用,效率会更高。

DirectByteBuffer细化又有两种,一种是通过jni申请一块堆外内存,还一种是直接引用mmap的内存地址,一般通过FileChannel.map调用返回。lucene的索引文件加载,有一种就是通过mmap得到的DirectByteBuffer,相比通过文件IO读取,减少了一次内存copy,而且把内存交给os管理,更简单。


原创粉丝点击