Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Direct memory usage in Netty 4

I have a problem about Netty's direct memory management.

I create a direct buffer by:

@GetMapping("/new/buffer/netty/unpool")
@Synchronized
public void newBufferNetty() {
    UnpooledByteBufAllocator allocator  = UnpooledByteBufAllocator.DEFAULT;
    ByteBuf buffer = allocator.buffer(100 * 1024 * 1024);
    _myByteBufList.add(buffer);
    log.info("buffer[{}] created", buffer);
}

Then I observed the info generated by top, and I found that there is no change about the memory (RES, SWAP and free). I was confused because it is alright (OS memory info will change) if I do it in NIO way like ByteBuffer.allocateDirect(1024*1024*100);.

After I investigated about the source code, I found that NIO create a directByteBuffer by new DirectByteBuffer(cap) and Netty in fact create it by new DirectByteBuffer(addr, cap). In latter way Netty did not call Bits.reserve(size, cap), which is the reason I think why there is no change shown by top.

And I also found that Netty uses its own counter DIRECT_MEMORY_COUNTER to keep track with the direct memory it allocates.

My question is:

  1. Why Netty does not call Bits.reserve when allocating direct memory ?

  2. Why Netty have to use its own counter to monitor the usage of direct memory ?

  3. (this is the one which confuses me most) Why there is no change about os memory when I create a Netty buffer (UnpooledUnsafeNoCleanerDirectByteBuf)

Thank you very much in advance.

like image 722
ruanhao Avatar asked Dec 02 '16 08:12

ruanhao


1 Answers

I answer only for 3 point. First 2 points can be explained only by Netty authors.

As mentioned in question Netty uses new DirectByteBuffer(addr, cap) for creating direct buffer. And passed memory address is one returned by Unsafe.allocateMemory which calls system memory allocation facilities. As said in https://en.wikipedia.org/wiki/C_dynamic_memory_allocation

On lazy memory allocation schemes, such as those often found in the Linux operating system, a large heap does not necessarily reserve the equivalent system memory; it will only do so at the first write time (reads of non-mapped memory pages return zero). The granularity of this depends on page size.

So, it is expected that top does not reflect Netty direct buffer allocation.

In contrast, ByteBuffer.allocateDirect uses Unsafe.setMemory to set all bytes to zero after allocating with Unsafe.allocateMemory. Such behaviour is specified in Javadoc https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#allocateDirect(int)

The new buffer's position will be zero, its limit will be its capacity, its mark will be undefined, and each of its elements will be initialized to zero.

It explains why allocation via ByteBuffer.allocateDirect is reflected by top. Note, that application memory usage is increased only after first use of allocated memory.

like image 126
Ivan Pavlukhin Avatar answered Sep 29 '22 02:09

Ivan Pavlukhin