我试图了解DirectByteBufferLinux 上的工作原理并编写了以下非常简单的程序以在 strace 下运行:public static void main(String[] args){ while(true){ ByteBuffer buffer = ByteBuffer.allocateDirect(8192); }}我期望实际上一些mmap或sys_brk系统调用直接从操作系统分配内存,但实际上它只是设置了请求页面的读写保护。我的意思是这样的:mprotect(0x7fa9681ef000, 8192, PROT_READ|PROT_WRITE) = 0这似乎是分配直接缓冲区比分配堆缓冲区慢的原因,因为每次分配都需要系统调用。如果我错了,请纠正我,但堆缓冲区分配(如果发生在 TLAB 内)相当于返回一个指向预分配堆内存的指针。问题:为什么我们不能对直接内存做同样的事情?返回一个指向预分配内存的指针?
1 回答
RISEBY
TA贡献1856条经验 获得超5个赞
在 Oracle/OpenJDK 中,ByteBuffer.allocateDirect(n)
使用Unsafe.allocateMemory(n)在 Linux 上调用malloc。
在 Linux 上,malloc 从内存池中分配较小的分配,例如 8KB,但是,对于 128 KB 或更多的分配,它会添加一个新的mmap
.
我实际上期望一些 mmap 或 sys_brk 系统调用直接从操作系统分配内存
尝试一次分配128 << 10
或 128 KB。
这似乎是分配直接缓冲区比分配堆缓冲区慢的原因,因为每次分配都需要系统调用。
系统调用增加了大约 2 微秒。不打算经常分配和释放直接的 ByteBuffer。您应该找到重用这些缓冲区的方法。
如果我错了,请纠正我,但堆缓冲区分配(如果发生在 TLAB 内)相当于返回一个指向预分配堆内存的指针。
正确的。本机内存中较小的分配使用本机堆。
问题:为什么我们不能对直接内存做同样的事情?
确实如此。
返回一个指向预分配内存的指针?
它不会为 128 KB+ 执行此操作以将内存释放回操作系统。
添加回答
举报
0/150
提交
取消