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