其中allocateDirect分配的字节缓冲区用中文叫做直接缓冲区(DirectByteBuffer),用allocate分配的ByteBuffer叫做堆字节缓冲区(HeapByteBuffer)..
其实根据类名就可以看出,HeapByteBuffer所创建的字节缓冲区就是在jvm堆中的,即内部所维护的java字节数组。而DirectByteBuffer是直接操作操作系统本地代码创建的内存缓冲数组(c、c++的数组)。
由于DirectByteBuffer操作的缓冲区是通过操作系统本地代码创建的,对于java来说创建和销毁DirectByteBuffer更消耗性能。而HeapByteBuffer内部是直接创建的java数组,对于java来说更快。可以根据下面的测试代码测试:
public static void directAndHeapSpeedCompare(){
int length=1000000;
directExecuteTime(length);
heapExecuteTime(length);
}
private static void directExecuteTime(int length){
long startTime=System.currentTimeMillis();
ByteBuffer[] byteBufferArray = new ByteBuffer[length];
for (int i = 0; i <length ; i++) {
byteBufferArray[i]=ByteBuffer.allocateDirect(1024);
}
long endTime=System.currentTimeMillis();
System.out.println("创建"+length+"个DirectByteBuffer所消耗的时间:"+(endTime-startTime));
}
private static void heapExecuteTime(int length){
long startTime=System.currentTimeMillis();
ByteBuffer[] byteBufferArray = new ByteBuffer[length];
for (int i = 0; i <length ; i++) {
byteBufferArray[i]=ByteBuffer.allocate(1024);
}
long endTime=System.currentTimeMillis();
System.out.println("创建"+length+"个HeapByteBuffer所消耗的时间:"+(endTime-startTime));
}
我的测试结果是:
创建1000000个DirectByteBuffer所消耗的时间:1443
创建1000000个HeapByteBuffer所消耗的时间:925
那么为什么创建DirectByteBuffer比HeapByteBuffer性能差却还使用DirectByteBuffer呢?
答:创建DirectByteBuffer的确不如HeapByteBuffer快,但是本地IO(从操作系统本地获取数据,比如文件、socket网络数据)修改数据DirectByteBuffer是更快的。因为:
HeapByteBuffer的缓冲区是java中的java数组,使用HeapByteBuffer读取一个文件,操作系统会先把文件读取到操作系统管理的内存中,然后在把操作系统管理的这块内存的数据复制到jvm管理的内存(即HeapByteBuffer管理的java字节数组)中,然后HeapByteBuffer对java字节数组进行操作。。
而DirectByteBuffer(1)先在操作系统内核所管理的内存缓冲区中(文件系统页)开辟一块内存空间(作为缓冲区),文件数据可以直接从操作系统复制到该缓冲区中(2)用户写入和读取数据就可以直接操作这块缓冲区。。。。比使用HeapByteBuffer少了一个步骤,效率自然提升了。
什么情况下使用DirectByteBuffer(ByteBuffer.allocateDirect(int))?
1、频繁的native IO,即缓冲区 中转 从操作系统获取的文件数据、或者使用缓冲区中转网络数据等
2、不需要经常创建和销毁DirectByteBuffer对象
3、经常复用DirectByteBuffer对象,即经常写入数据到DirectByteBuffer中,然后flip,再读取出来,最后clear。。反复使用该DirectByteBuffer对象。
而且,DirectByteBuffer不会占用堆内存。。也就是不会受到堆大小限制,只在DirectByteBuffer对象被回收后才会释放该缓冲区。
什么情况下使用HeapByteBuffer(ByteBuffer.allocate(int))?
1、同一个HeapByteBuffer对象很少被复用,并且该对象经常是用一次就不用了,此时可以使用HeapByteBuffer,因为创建HeapByteBuffer开销比DirectByteBuffer低。(但是!!创建所消耗时间差距只是一倍以下的差距,一般一次只会创建一个DirectByteBuffer对象反复使用,而不会创建几百个DirectByteBuffer,所以在创建一个对象的情况下,HeapByteBuffer并没有什么优势,所以,开发中要使用ByteBuffer时,直接用DirectByteBuffer就行了)
总结:
HeapByteBuffer和DirectByteBuffer
1、HeapByteBuffer就是创建效率高,读取和写入的效率低。
2、DirectByteBuffer是创建效率低,读取和写入的效率高。