java - 我可以使用 java 内存映射文件 (MappedByteBuffer) 处理大于系统内存的文件吗?
问题描述
- MappedByteBuffer 是如何工作的?当我像这样创建一个 MappedByteBuffer 对象时:</li>
RandomAccessFile in = new RandomAccessFile("./src/test.txt", "rw");
FileChannel Fcin = in.getChannel();
MappedByteBuffer mapBuff = Fcin.map(FileChannel.MapMode.READ_WRITE, 0, 0xFFFF);
这是否意味着 MappedByteBuffer 对象包含该文件的所有内容?
2.如果1的答案是YES,这句话在Thinking in Java (page 692)中如何解释?
内存映射文件允许您创建和修改太大而无法放入内存的文件
3.当isLoaded()的返回值对一个MappedByteBuffer对象为真时是什么意思?
解决方案
有很多问题,但都是相关的,所以我将尝试全部回答:
我可以使用 java 内存映射文件 (MappedByteBuffer) 处理大于系统内存的文件吗?
在使用虚拟内存的最新操作系统(实际上我知道的所有当前操作系统)上,答案是肯定的,你可以
MappedByteBuffer 是如何工作的?
这在很大程度上取决于底层操作系统如何处理内存映射文件。大多数时候,它声明了一堆映射到文件内容的虚拟内存。这意味着MappedByteBuffer
包含文件数据的映像,但某些页面可能没有映射到物理内存(即:实际数据仅在磁盘文件上)
这是否意味着 MappedByteBuffer 对象包含该文件的所有内容?
是的。至少实际上是因为数据可以按需加载到内存中。
如果 1 的答案是 YES,那么 Thinking in Java 如何解释这句话...
借助虚拟内存,当您处理大于可用内存的文件时,大部分数据仍保留在磁盘上。如果您尝试访问当前未映射的数据,则虚拟内存系统将(最终丢弃一些其他内存页面并)将包含请求数据的页面映射到物理内存页面以(几乎)透明地访问该数据。
当 isLoaded() 的返回值对 MappedByteBuffer 对象为真时,这意味着什么?
这暗示缓冲区的全部内容都驻留在物理内存中。但是 Javadoc 清楚地表明它不是保证,它严重依赖于操作系统。
长话短说,内存映射文件是一个很好的工具,它允许处理磁盘文件,就好像它是一个(可能是巨大的)字节数组一样。可能的缺点是它很容易创建性能很差的程序,因为整个磁盘 IO 对程序员是隐藏的,就像系统花时间将内存页面存储到磁盘并再次加载它们时一样。最后,您可能有一个看起来像内存的漂亮缓冲区,但具有磁盘 IO 访问时间。
我的建议是,在使用它之前,程序员应该想知道所涉及的磁盘 IO 是什么。在某些用例中,它会比手动读取和处理文件更快,因为所有访问都保证是页面对齐的,而在其他用例中,这将是一场灾难,因为非连续访问将需要大量的磁盘访问。
推荐阅读
- java - 在多节点 Spark 集群上运行时 Dataframe.collectAsList 方法的 Spark 问题
- lua - 尝试索引全局“消息”(一个零值)Lua 消息脚本
- sql - 在不同的数据库服务器中运行相同的查询但结果不同
- javascript - 注册为回调的命名箭头函数的正确语法是什么?
- django - 如何在 Django admin 中显示实际的外键 ID?
- haskell - submonand 泄漏(带有 forM_ 的 blaze-html 空输出)
- python - 通过系统推送数据的软件范式
- mysql - 如何在MYSQL中将一个表中的行插入到另一个表中
- python - 通过 for 循环创建字典 (?)
- python - Plotly Dash 应用程序未运行