Netty pristine play to the NIO buffer

Source: Internet
Author: User

Absrtact: in Java NIO-related components, Bytebuffer is another important component in addition to the selector, channel, which is a buffer that deals directly with the channel, usually in a scene or from Bytebuffer to the channel, or read buffer from the channel, and in Netty, the carefully designed BYTEBUF is the core buffer Netty throughout the development process, so what's the difference between them? Netty for the design of the buffer zone for high-performance applications and bring some ideas for reference? Based on the introduction of the basic concepts of bytebuffer and bytebuf, this paper compares the two, and then expands the Bytebuf family in Netty.

In Java NIO-related components, Bytebuffer is another important component besides the selector, channel, which is a buffer that deals directly with the channel, usually in scenes or from Bytebuffer to the channel, or read buffer from the channel, and in Netty, the carefully designed BYTEBUF is the core buffer Netty throughout the development process, so what's the difference between them? Netty for the design of the buffer zone for high-performance applications and bring some ideas for reference? Based on the introduction of the basic concepts of bytebuffer and bytebuf, this paper compares the two, and then expands the Bytebuf family in Netty.

JAVA NiO's Bytebuffer

In JAVA NiO, the channel acts as an abstraction to an entity that has an I/O operation attribute, where I/O operations are usually referred to as readding/writing, while entities with I/O operations properties such as I/O devices, files, network sockets, and so on. It's not possible to have a channel, we have to add readding/writing to him, so Java NiO expands the Writablebytechannel and Readablebytechannel interfaces based on the channel. Since the focus of this article is on Bytebuffer, we see this in the design of the channel, because with Writablebytechannel and Readablebytechannel, we can operate on Bytebuffer, Take a look at the two interfaces they provide:

PublicIntRead(Bytebuffer DST)  Throws ioexception; public  int   Write (BYTEBUFFER SRC) Span class= "hljs-function" >  throws ioexception;        

From the above interface we can see the two basic behaviors that occur between the channel and the Bytebuffer, namely readding/writing. Whether you read or write to the file (FileChannel) or the network (Socketchannel), they will implement these two basic behaviors. Well, we've got a general understanding of Bytebuffer's position and role in Java NIO, so let's go into a little bit of understanding bytebuffer.

Bytebuffer has four important attributes: Mark, position, limit, capacity, and two important methods: Flip and clear. The underlying storage structure of Bytebuffer for heap memory and direct memory, respectively, as a byte[] object on the heap and as an area of memory allocated directly on memory. Since it is an area of memory, we can read and write byte-based, while Bytebuffer's four-type properties are pointers to this area:

    1. Position: A read-write pointer that represents the position of the current read or write operation, which is always less than or equal to limit.

    2. Mark: In the process of using Bytebuffer, if you want to remember the current position, the current position value will be given to mark so that when it needs to be restored, Mark's value will be given to position.

    3. Capacity: Represents the size of this area of memory.

    4. Limit: In the initial buffer, the values of limit and capacity are equal, and this value is usually manipulated during clear and flip operations, and the value and capacity are set to equal when the clear operation When flip will give the current value of position to limit, we can summarize when writing, the value of limit represents the largest writable position, while reading, the value of limit represents the maximum readable position. Clear is to prepare for writing, Flip is to prepare for reading.

Bytebuffer pointer

In Java NIO, the native members of the Bytebyffer family are simple, mainly Heapbytebuffer, Directbytebuffer, and Mappedbytebuffer:

    1. Heapbytebuffer is a buffer based on the byte array on the heap as a storage structure.

    2. Directbytebuffer is a buffer that is based on the memory area of the direct memory as a storage structure.

    3. Mappedbytebuffer is primarily file-manipulation related, which provides a mechanism based on virtual memory mapping that allows us to manipulate files as if it were a file, without having to update the content to a file each time, while reading and writing is very efficient.

The Bytebuf of Netty

Compared to the Bytebuffer read-write pointer position,bytebuf provides two pointers readerindex and Writeindex to point to the read position and the location of the write, do not need to prepare for reading and writing each time, directly set reading and writing pointers to read and write operations. Let's look at the state in the middle:

Buffer for reading and writing intermediate states

The area between the beginning and the Readerindex pointer is the area that can be discarded, and later, the area between the Readerindex and Writerindex pointers can be read, The area between the writerindex and capacity pointers is an area that can be written. When the Writerindex pointer reaches the top, BYTEBUF allows the user to reuse the previously read area, calling the Discardreadbytes method, which corresponds to the state above, and the following status after the call Discardreadbytes:

Reclaim available zones after calling Discardreadbytes

In addition to the Discardreadbytes method, another important method is clear, clear that clears the buffer pointer state, revert to the initial value, corresponding to the middle state of the graph, called clear after the state as follows:

When clear is called, the pointer state of the buffer state is initialized

Characteristics of Netty Bytebuf

Here want to compare two kinds of buffer, compare Bytebuffer to draw bytebuf Advantage Point, we must first do is summarizes bytebuf characteristic and compare bytebuffer, this characteristic how to become the merit:

(1) Bytebuf reading and writing pointers

In the Bytebuffer, read and write pointers are position, and in Bytebuf, read and write pointers are Readerindex and writerindex, the intuitive look bytebuffer only a pointer to achieve the function of two pointers, saving variables, However, the flip method must be called when the read-write state of the Bytebuffer is switched, and the contents of the Buffe must be read before the next write, and then the clear method is called. Before each reading, call Flip, write before the call clear, which undoubtedly brings tedious steps to development, and the content is not read is not written, this is very inflexible. In contrast, we look at Bytebuf, read only rely on the readerindex pointer, when writing only rely on the Writerindex pointer, do not need to call the corresponding method before each read and write, and there is no need to read the limit.

(2) Bytebuf reference count

BYTEBUF extends the Referencecountered interface, which defines the function primarily as a reference count:

Referencecountered Interface Definition

That is, all the implementation of the BYTEBUF, to implement the reference count, Netty the buffer resource is explicitly managed, this part to be combined with Netty memory pool technology understanding, when buffer reference +1, you need to call retain to let refcnt+ 1, when the buffer reference number-1 need to call release to let RefCnt-1, when refcnt becomes 0 Netty for the pooled and unpooled different buffer provides a different implementation, usually for non-memory pool usage, Netty the memory of buffer to the garbage collector, for the use of memory pool, Netty the memory of the collection is actually recycled into the memory pool to provide the next request to use, about the memory pool This section can refer to my previous article.

(3) Pooling buffer resources

Since Netty is a NIO network framework, the use of buffer can greatly improve the efficiency of I/O operations if it is implemented based on direct memory (Directbuffer), whereas Directbuffer and heapbuffer in contrast to i/ o High operational efficiency there is a natural disadvantage, that is, the application of directbuffer compared to heapbuffer efficiency is lower, so netty combined with reference counting to achieve polledbuffer, that is, the use of pooling, when the reference count equals 0, Netty buffer is recycled into the pool and will be reused at some point in the next request for buffer. Netty The basic idea is that we have spent a great amount of effort to apply for a piece of memory, not easy to let him be recycled, can reuse of course, re-use.

(3) Bytebuffer to deal with the channel

In the final analysis, all buffers in the NIO position want to deal with the channel, in other words, when the data is read from the network channel, from the channel to the Bytebuffer, from the buffer line written on the internet, are from Bytebuffer to channel. Therefore, when the Netty hears an I/O read event, it streams itself from the channel to the Bytebuffer instead of the bytebuf,see below:

return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length));

Above is one of BYTEBUF's specific read implementation, you can see Bytebuf maintain an internal bytebuffer, called Internalniobuffer. When you need to write a byte stream to the network, you need to convert Bytebuf to Bytebuffer,see below:

 ByteBuffer tmpBuf;    if (internal) {        tmpBuf = internalNioBuffer();    } else {        tmpBuf = ByteBuffer.wrap(array);    }    return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length));}

Above is one of Bytebuf's specific write implementation, before writing, will always turn bytebuf into Bytebuffer.

A little summary of this section, the design of the bytebuf itself, in terms of pointers with two read and write pointers respectively for reading and writing pointers, which reduces the difficulty and error rate of buffer use, conceptual understanding is relatively simple. In Netty, each requested buffer may be a valuable resource for netty, so in order to gain more control over the application and recovery of memory, Netty himself to the memory management according to the reference counting method, In addition, the well-designed pooling algorithm controls the use of memory to a greater extent, although it is slightly more complex to achieve manageable, pooled buffer than simple application-use-release, but it is definitely worthwhile to make some contribution to Netty's superior performance data. Finally, we have to clarify the concept, JAVA NiO and channel can only deal with Bytebuffer,netty in the read and write before the conversion, so do not confuse, bytebuf or BYTEBUF, it is not bytebuffer.

Netty's large buffer family

This section describes the Netty of the buffer family, bytebuf families are huge, but we can sort out the routines to classify them, so that it does not seem so complicated, netty mainly around the 2*2 dimension of the buffer expansion, respectively:

Directbuffer

Heapbuffer

Pooledbuffer

Unpooledbuffer

The abstraction of the top layer is that Bytebuf,netty first expands the buffer in these two directions based on direct memory and heap memory, and then expands the specific direct memory and heap memory buffers in the two directions of the pool session, respectively. In addition to these two dimensions, Netty also expands the unsafe-based buffer, and we have singled out a more typical implementation to introduce:

POOLEDHEAPBYTEBUF: Pooled heap-based buffer.

POOLEDDIRECTBYTEBUF: Pooled Direct memory based buffers.

POOLEDUNSAFEDIRECTBYTEBUF: Pooling of buffers based on unsafe and direct memory implementations.

UNPOOLEDHEAPBYTEBUF: Non-pooled heap memory-based buffers.

UNPOOLEDDIRECTBYTEBUF: A non-pooled, direct-memory-based buffer.

UNPOOLEDUNSAFEDIRECTBYTEBUF: Non-pooled buffers based on unsafe and direct memory implementations.

In addition to the above, the other Netty buffer family also have compositebytebuf, Readonlybytebufferbuf, Threadlocaldirectbytebuf and so on, here also to say Unsafebuffer , when the current platform supports unsafe, we can use the Unsafebuffer,java Directbuffer implementation is also based on unsafe to operate the memory, We can see that the difference is that pooledunsafedirectbytebuf or UNPOOLEDUNSAFEDIRECTBYTEBUF maintains a memoryaddress variable that represents the memory address of the buffer, The use of the process of adding an offer to the memory can be flexible operation. In general, the behavior defined by Netty around the BYTEBUF and its parent interface is either direct memory or heap memory, pool session or non-pooled, and whether or not unsafe is supported to implement different extensions to bytebuf.

Netty pristine play to the NIO buffer

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.