ByteBuffer内存分配

时间:2018-10-06 08:05:21

标签: java jvm bytebuffer

我试图了解DirectByteBuffer在Linux上的工作方式,并编写了以下非常简单的程序以在strace下运行:

public static void main(String[] args){
    while(true){
        ByteBuffer buffer = ByteBuffer.allocateDirect(8192);
    }
}

我实际上期望一些mmapsys_brk系统调用直接从操作系统分配内存,但是实际上它只是设置了read和  对请求的页面进行写保护。我的意思是:

mprotect(0x7fa9681ef000, 8192, PROT_READ|PROT_WRITE) = 0

这似乎是分配直接缓冲区比分配堆缓冲区慢的原因,因为它需要每次分配进行syscall。

如果我错了,请纠正我,但是堆缓冲区分配(如果发生在TLAB中)等效于返回指向预分配堆内存的指针。

问题: 为什么我们不能对直接存储做同样的事情?返回指向预分配内存的指针?

1 个答案:

答案 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 +不会执行此操作以将内存释放回操作系统。