rua*_*hao 5 java memory nio netty
我有一个关于Netty直接内存管理的问题.
我创建了一个直接缓冲区:
@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);
}
Run Code Online (Sandbox Code Playgroud)
然后我观察了生成的信息top,我发现内存没有变化(RES,SWAP和free).我很困惑,因为它是好的(操作系统内存信息会改变),如果我用NIO方式做的话ByteBuffer.allocateDirect(1024*1024*100);.
在我调查了源代码之后,我发现NIO创建了一个directByteBuffer,new DirectByteBuffer(cap)而Netty实际上创建了它new DirectByteBuffer(addr, cap).后一种方式,Netty没有打电话Bits.reserve(size, cap),这就是我认为为什么没有显示出变化的原因top.
我还发现Netty使用自己的计数器DIRECT_MEMORY_COUNTER来跟踪它分配的直接内存.
我的问题是:
为什么Netty Bits.reserve在分配直接内存时不会调用?
为什么Netty必须使用自己的计数器来监控直接内存的使用?
(这是让我最困惑的一个)当我创建一个Netty缓冲区时,为什么os内存没有变化(UnpooledUnsafeNoCleanerDirectByteBuf)
非常感谢你提前.
小智 3
我只回答3分。前两点只能由 Netty 作者解释。
正如问题中提到的,Netty 用于new DirectByteBuffer(addr, cap)创建直接缓冲区。传递的内存地址是Unsafe.allocateMemory调用系统内存分配工具返回的地址。正如https://en.wikipedia.org/wiki/C_dynamic_memory_allocation中所述
在惰性内存分配方案中,例如 Linux 操作系统中常见的方案,大堆不一定会保留等效的系统内存;它只会在第一次写入时执行此操作(读取非映射内存页返回零)。其粒度取决于页面大小。
因此,预计top不会反映 Netty 直接缓冲区分配。
相反,ByteBuffer.allocateDirect使用Unsafe.setMemory分配后将所有字节设置为零Unsafe.allocateMemory。Javadoc https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#allocateDirect(int)中指定了此类行为
新缓冲区的位置将为零,其限制将是其容量,其标记将是未定义的,并且其每个元素将被初始化为零。
它解释了为什么分配viaByteBuffer.allocateDirect由 反映top。请注意,应用程序内存使用量仅在首次使用分配的内存后才会增加。