I believe we all know, but where is the difference? What kind of bytebuffer is more efficient in different environments?
First explain the difference between the two:
Non-directbytebuffer memory is allocated on the heap, directly by the Java Virtual Machine is responsible for garbage collection, you can think of it as a byte array wrapper class, as shown in the following pseudo code:
Heapbytebuffer extends Bytebuffer {
byte[] content;
int position, limit, capacity;
......
}
Instead, Directbytebuffer allocates a chunk of memory outside the Java Virtual machine through JNI (so even if the maximum heap memory of the Java Virtual machine is specified by-XMX at run time, it is possible to instantiate a directbytebuffer that exceeds that size). This block of memory is not directly responsible for garbage collection by the Java virtual machine, but it is freed by the Java reference mechanism when the Directbytebuffer wrapper class is recycled. The following pseudo code is shown:
Directbytebuffer extends Bytebuffer {
Long address;
int position, limit, capacity;
protected void Finalize () throws throwable{
Frees the memory block, the code is only for demonstration, the real Directbytebuffer is not released through finalize
Releaseaddress ();
......
}
......
}
I believe most of my friends should know the difference above, so what are the other differences? Hey, let's go a little deeper, turn to Sun.nio.ch.IOUtil.java, most of the channel class is through this tool class and the outside world to communicate, such as Filechannel/socketchannel and so on. I simply use pseudo-code to express the Write method (the Read method is similar, do not explain more)
int write (Bytebuffer src, ...) {
if (src instanceof directbuffer)
Return Writefromnativebuffer (...);
Bytebufferdirect = Gettemporarydirectbuffer (src);
Writefromnativebuffer (direct,......);
Updateposition (SRC);
Releasetemporarydirectbuffer (direct);
}
Yes, the Non-directbytebuffer is converted to Directbytebuffer before sending and receiving, and then the related operation is done, and the position of the original Bytebuffer is finally updated. What does that mean? Suppose we want to read a piece of data from the network and send it out,
The process of using Non-directbytebuffer is this:
Network--Temporary Directbytebuffer--non-directbytebuffer---temporary directbytebuffer--Network
The process of using Directbytebuffer is this:
Network--Application Directbytebuffer--Network
You can see that at least two times of memory copy can be saved in addition to the time of construction and destruction of temporary directbytebuffer. So is directbuffer used in all cases?
No. For most applications, the time of two memory copies is negligible, while the time to construct and refactor Directbuffer is relatively long. In the implementation of the JVM, some methods cache a subset of temporary directbytebuffer, meaning that if the use of Directbytebuffer can only save two times of memory copy, but not the time to save the construction and destruction. In the case of Sun implementations, the write (Bytebuffer) and read (Bytebuffer) methods will cache temporary Directbytebuffer, while write (bytebuffer[]) and read (bytebuffer[]) Each time a new temporary directbytebuffer is generated.
Based on these differences, I would like to make the following recommendations:
· If you do small to medium sized applications (where the application size is divided by the number and size of bytebuffer used), and don't care about the damn details, choose Non-directbytebuffer If the performance after Directbytebuffer does not appear the change you expect, select Non-directbytebuffer If you do not have directbytebuffer Pool, try not to use Directbytebuffer Unless you are sure that the bytebuffer will exist for a long time and interact frequently with the outside world, you can use Directbytebuffer If Non-directbytebuffer is used, then the Write/read (bytebuffer) effect with non-aggregation (gather) may instead exceed the aggregated write/read (bytebuffer[]), because the aggregated write/ Temporary directbytebuffer of Read are non-cached
Basically, using Non-directbytebuffer is always right! Because the cost of a memory copy is negligible for most applications. However, I do a large-scale network concurrency framework, so it is necessary to have a deep understanding of these details, and according to these details to adjust their buffer inheritance system (again complaining that bytebuffer can not be extended is a very very very confusing design)
Note: As mentioned earlier, "even if the maximum heap memory of a Java virtual machine is specified through-XMX at run time, or if directbytebuffer that exceeds that size may be instantiated," it may refer to the possibility of-xx:maxdirectmemorysize=<size > To specify the maximum amount of memory that the Directbytebuffer instance can use. If you specify-xx:maxdirectmemorysize=1024, all surviving Directbytebuffer total memory in the system cannot exceed 1024 bytes.
Favorites: Non-direct and direct Bytebuffer differences