什么是映射缓冲池/直接缓冲池以及如何增加其大小?
VisualVM的屏幕截图是在我运行IO密集型JVM程序(用Scala编写的)时拍摄的,堆大小为4 GB,只有2 GB正在使用中。JVM 程序使用内存映射文件。
“映射缓冲池”和“直接缓冲池”是什么意思?
这些游泳池似乎非常满。由于 JVM 程序使用内存映射文件,如果池较大,我会看到性能提高吗?如果是这样,如何增加它们的大小?
所有映射文件的大小约为1.1GB。
VisualVM的屏幕截图是在我运行IO密集型JVM程序(用Scala编写的)时拍摄的,堆大小为4 GB,只有2 GB正在使用中。JVM 程序使用内存映射文件。
“映射缓冲池”和“直接缓冲池”是什么意思?
这些游泳池似乎非常满。由于 JVM 程序使用内存映射文件,如果池较大,我会看到性能提高吗?如果是这样,如何增加它们的大小?
所有映射文件的大小约为1.1GB。
直接缓冲液
直接缓冲区是一块内存,通常用于将 Java 连接到操作系统 I/O 子系统,例如,作为操作系统在从套接字或磁盘接收数据时写入数据的位置,以及 Java 可以直接读取数据的位置。
与操作系统共享缓冲区比将数据从操作系统复制到Java内存模型的原始方法要有效得多,这使得数据受到垃圾回收和低效率的影响,例如在从伊甸园 ->幸存者 ->永久>迁移到永久一代时重新复制数据。
在屏幕截图中,您只有一个16KB的直接缓冲区。Java将根据需要扩展此池,因此蓝色区域位于块顶部的事实只是一个声明,即到目前为止分配的所有缓冲区内存都在使用中。我不认为这是一个问题。
映射缓冲池
映射的缓冲池是 Java 用于其 FileChannel 实例的所有内存。
每个 FileChannel 实例都有一个与操作系统共享的缓冲区(类似于具有所有效率优势的直接缓冲区)。内存本质上是文件一部分的 RAM 窗口。根据模式(读、写或两者兼而有之),Java 可以直接读取和/或修改文件的内容,操作系统可以直接向磁盘提供数据或将修改后的数据刷新到磁盘。
此方法的其他优点是,操作系统可以根据需要将此缓冲区直接刷新到磁盘,例如,当操作系统关闭时,操作系统可以锁定该文件的该部分,使其免受计算机上的其他进程的影响。
屏幕截图表明 12 个 FileChannel 对象正在使用大约 680MB。同样,Java会增长,这是Scala需要的更多(JVM可以从操作系统获得额外的内存),所以所有680MB都在使用的事实并不重要。考虑到它们的大小,在我看来,程序已经进行了优化,可以有效地使用这些缓冲区。
增加映射缓冲池的大小
Java 在垃圾回收空间之外为文件通道缓冲区分配内存。这意味着正常的堆大小参数(如)在这里并不重要-Xmx
文件通道中缓冲区的大小是使用映射方法设置的。改变这一点需要改变你的Scala程序
一旦缓冲区达到阈值大小(10s-100s 的 KB),增加 FileChannel 缓冲区大小可能会也可能不会提高性能 - 这取决于程序如何使用缓冲区:
尝试分析应用程序并查找I / O等待(Jprofiler和YourKit擅长于此)。可能是文件 I/O 实际上不是问题 - 不要成为过早优化的受害者。如果 I/O 等待时间占总运行时间的很大一部分,则可能值得尝试更大的缓冲区大小
更多信息
https://blogs.oracle.com/alanb/entry/monitoring_direct_buffers
另请注意,JVM上报告了一个错误,指出FileChannel不擅长释放内存。有关细节,请参阅使用 java.nio.MappedByteBuffer 时防止 OutOfMemory