java - Netty 4 中的直接内存使用

标签 java memory netty nio

我对 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、SWAP、free)没有变化。我很困惑,因为如果我像 ByteBuffer.allocateDirect(1024*1024*100); 那样以 NIO 方式执行它就没问题(操作系统内存信息会改变)。

我查了一下源码,发现NIO是通过new DirectByteBuffer(cap)创建directByteBuffer,而Netty实际上是通过new DirectByteBuffer(addr, cap)。在后一种方式中,Netty 没有调用 Bits.reserve(size, cap),这就是我认为 top 没有显示任何变化的原因。

而且我还发现 Netty 使用它自己的计数器 DIRECT_MEMORY_COUNTER 来跟踪它分配的直接内存。

我的问题是:

  1. 为什么 Netty 在分配直接内存时不调用 Bits.reserve

  2. 为什么 Netty 必须使用自己的计数器来监控直接内存的使用情况?

  3. (这是最让我困惑的)为什么当我创建一个 Netty 缓冲区(UnpooledUnsafeNoCleanerDirectByteBuf)时,操作系统内存没有变化

非常感谢您。

最佳答案

我只回答 3 分。前两点只能由 Netty 作者解释。

正如问题中提到的,Netty 使用 new DirectByteBuffer(addr, cap) 来创建直接缓冲区。传递的内存地址是调用系统内存分配工具的 Unsafe.allocateMemory 返回的地址。如 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.

因此,预计 top 不会反射(reflect) Netty 直接缓冲区分配。

相比之下,ByteBuffer.allocateDirect 使用Unsafe.setMemory 在使用Unsafe.allocateMemory 分配后将所有字节设置为零。此类行为在 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.

它解释了为什么 top 反射(reflect)了通过 ByteBuffer.allocateDirect 进行的分配。请注意,只有在首次使用分配的内存后,应用程序内存使用量才会增加。

关于java - Netty 4 中的直接内存使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40927651/

相关文章:

java - Apache Lucene 中的索引性能

java - 在 Java 中从数组中提取单个随机字符串

java - Spring错误-org.springframework.beans.factory.NoSuchBeanDefinitionException

java - GWT 客户端代码中的 volatile 变量

java - ChannelFuture 监听器注册是否可靠?

javascript - 我在哪里可以下载用于 Java 7 的 rt.jar?

android - 分配游标时内存不足

C 扫描内存的指针

java - netty中如何在断开连接后自动连接到TCP服务器

java - Netty 中没有密码套件