Direct memory usage in Netty 4

I have a problem with Netty direct memory management.

I create a direct buffer:

@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 noticed the information generated by top , and I found that there were no changes in memory (RES, SWAP, and free). I was confused because everything is fine (OS memory information will change) if I do this in NIO, like ByteBuffer.allocateDirect(1024*1024*100); .

After I examined the source code, I found that NIO creates directByteBuffer using new DirectByteBuffer(cap) , and Netty actually creates it using new DirectByteBuffer(addr, cap) . In the latter case, Netty did not call Bits.reserve(size, cap) , so I think why there are no changes shown by top .

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

My question is:

  • Why is Netty not called by Bits.reserve when allocating direct memory?

  • Why should Netty use its own counter to monitor direct memory usage?

  • (this is the one that bothers me more). Why there are no changes in os memory when creating a Netty buffer (UnpooledUnsafeNoCleanerDirectByteBuf)

Thank you in advance.

+5
source share
1 answer

I am only responsible for 3 points. The first 2 points can only be explained by Netty.

As mentioned in the question, Netty uses new DirectByteBuffer(addr, cap) to create a direct buffer. And the accepted memory address is the one returned by Unsafe.allocateMemory , which calls the system memory Unsafe.allocateMemory . As stated in https://en.wikipedia.org/wiki/C_dynamic_memory_allocation

In lazy memory allocation schemes, such as those commonly found on the Linux operating system, a large heap does not necessarily reserve equivalent system memory; he will do this only at the first time of writing (reading unmarked pages of memory returns zero). The granularity of this depends on the size of the page.

So, it is expected that top does not reflect the distribution of the direct Netty buffer.

In contrast, ByteBuffer.allocateDirect uses Unsafe.setMemory to set all bytes to zero after allocation using Unsafe.allocateMemory . This behavior is indicated in the Javadoc https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#allocateDirect(int)

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

This explains why distribution through ByteBuffer.allocateDirect reflected top . Please note that application memory usage increases only after the first use of allocated memory.

0
source

Source: https://habr.com/ru/post/1260691/


All Articles