转载于:http://crmky.spaces.live.com/Blog/cns!8C989768DB1A6B14!458.entry?sa=254330365 这两种类型的ByteBuffer相信大家都知道,但是两者的区别在什么地方呢。在不同的环境下采用哪种类型的ByteBuffer会更有效率呢。
Let's explain the difference between the two:
Non-direct Bytebuffer Memory is allocated on the heap, directly by the Java Virtual machine responsible for garbage collection, you can think of it as a byte array of wrapper class, as the following pseudo code shows:
Heapbytebuffer extends Bytebuffer {
byte[] content;
int position, limit, capacity;
......
}
Direct Bytebuffer is allocated a piece of memory outside the Java Virtual machine via JNI (so even if the maximum heap memory of the Java Virtual machine is specified at run time through-XMX, or it is possible to instantiate direct bytebuffer that exceeds that size), The memory block is not directly responsible for garbage collection by the Java virtual machine, but when the direct Bytebuffer wrapper class is reclaimed, the memory block is freed through the Java reference mechanism. The following pseudo code shows:
Directbytebuffer extends Bytebuffer {
Long address;
int position, limit, capacity;
protected void Finalize () throws throwable{
Frees the memory block, which is used only to demonstrate that the true direct Bytebuffer is not released through finalize
Releaseaddress ();
......
}
......
}
I believe most of my friends should know the difference, so what's the difference? Hey, let's go a little deeper, turn to Sun.nio.ch.IOUtil.java, the vast majority of channel classes are through this tool class and the outside communication, such as Filechannel/socketchannel and so on. I simply use the pseudo code to express the Write method (read method is similar, do not do more explanation)
int write (Bytebuffer src, ...) {
if (src instanceof directbuffer)
Return Writefromnativebuffer (...);
Bytebuffer Direct = Gettemporarydirectbuffer (SRC);
Writefromnativebuffer (direct,......);
Updateposition (SRC);
Releasetemporarydirectbuffer (direct);
}
Yes, convert the Non-direct bytebuffer to direct bytebuffer before sending and receiving, then do the related operation, and finally update the position of the original bytebuffer. What this means. Suppose we want to read a piece of data from the network, and then send this data out, the process of adopting Non-direct Bytebuffer is this:
Network--> Temporary Direct bytebuffer--> application non-direct bytebuffer--> temporary direct bytebuffer--> Network
And the process of using direct Bytebuffer is this:
Network--> application Direct bytebuffer--> Network
As you can see, you can save at least two times of memory copies, except when you construct and deconstruct temporary direct bytebuffer. So are you using direct buffer in any case?
No. For most applications, the time of two memory copies is almost negligible, while the time to construct and deconstruct direct buffer is relatively long. In the JVM implementation, some methods cache part of the temporary direct bytebuffer, meaning that direct Bytebuffer can save only two times of memory copies without saving the time of construction and destructor. For the Sun's implementation, the Write (Bytebuffer) and read (Bytebuffer) methods cache temporary direct Bytebuffer, and write (bytebuffer[) and read (bytebuffer[) A new temporary direct bytebuffer is generated each time.
Based on these differences, I would like to make the following recommendations:
· 如果你做中小规模的应用(在这里,应用大小是按照使用ByteBuffer的次数和规模来做划分的),而且并不在乎这该死的细节问题,请选择Non-direct ByteBuffer · 如果采用Direct ByteBuffer后性能并没有出现你所期待的变化,请选择Non-direct ByteBuffer · 如果没有Direct ByteBuffer Pool,尽量不要使用Direct ByteBuffer · 除非你确定该ByteBuffer会长时间存在,并且和外界有频繁交互,可采用Direct ByteBuffer · 如果采用Non-direct ByteBuffer,那么采用非聚集(gather)的write/read(ByteBuffer)效果反而可能超出聚集的write/read(ByteBuffer[]),因为聚集的write/read的临时Direct ByteBuffer是非缓存的
Basically, using Non-direct bytebuffer is always right. Because the overhead required for a memory copy is negligible for most applications. But what I do is a large-scale network concurrency framework, so it is necessary to have a deep understanding of these details, and to adjust the buffer inheritance system based on these details (again complaining that Bytebuffer cannot be expanded is a very, very confusing design)
Note: "Even if the maximum heap memory of a Java virtual machine is specified at run time through-XMX, or it is possible to instantiate a direct bytebuffer that exceeds that size, it is possible to refer to the-xx:maxdirectmemorysize=<size > To specify the maximum amount of memory that can be used by the direct Bytebuffer instance. If you specify-xx:maxdirectmemorysize=1024, the total memory of all the live direct bytebuffer in the system cannot exceed 1024 bytes.