我对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);
}然后,我观察了top生成的信息,发现内存没有任何变化(RES、交换和空闲)。我很困惑,因为如果我像ByteBuffer.allocateDirect(1024*1024*100);那样以NIO的方式做这件事的话(操作系统内存信息会改变),那就很好了。
在研究了源代码之后,我发现NIO通过new DirectByteBuffer(cap)创建了一个new DirectByteBuffer(cap),而Netty实际上是通过new DirectByteBuffer(addr, cap)创建的。以后一种方式,Netty没有调用Bits.reserve(size, cap),这就是我认为top没有显示任何更改的原因。
我还发现Netty使用自己的计数器DIRECT_MEMORY_COUNTER来跟踪它分配的直接内存。
我的问题是:
Bits.reserve?先谢谢你。
发布于 2018-03-22 10:28:38
我只回答3分。前2点只能由Netty作者解释。
如前所述,Netty使用new DirectByteBuffer(addr, cap)创建直接缓冲区。所传递的内存地址是由Unsafe.allocateMemory返回的,它调用系统内存分配设施。正如在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)中指定。
新缓冲区的位置为零,限制为容量,标记未定义,每个元素将初始化为零。
它解释了为什么通过ByteBuffer.allocateDirect的分配是由top反映的。注意,应用程序内存使用率只有在第一次使用分配的内存后才会增加。
https://stackoverflow.com/questions/40927651
复制相似问题