java - java中大文件的快速随机访问读/写访问
问题描述
我正在为游戏创建残局数据库文件。多个线程计算游戏位置的结果,将结果保存在文件中的适当位置,但也咨询 sofar 数据库以加快计算速度。
到目前为止,我刚刚将一个 byte[] 加载到内存中,但是今天早上它在尝试创建一个超过 Integer.MAX_VALUE 字节的文件时崩溃了。
我考虑两种解决方案:
- 使用多字节数组的包装器
- 随机文件访问
随机文件访问也很好,因为它超出了我的 RAM 的限制。我希望操作系统(Windows 10/Linux Mint 20)将大部分文件加载到 RAM 中,这样对于完全适合 RAM 的文件,它的速度与 byte[] 一样快,否则不会太糟糕(我有一个非常快的 SSD)。
那行得通还是我什至不应该打扰?
解决方案
在 Java 中处理大文件的主要选项很少。
随机存取文件API
临:
- 简单但老派的 API
缺点:
- API 调用繁重(Java 调用和系统调用)并且从性能的角度来看不是最理想的。
此 API 可能仍然适用于简单的只读或只写情况。
文件通道API
与RandomAccesFile
此类相比,提供面向缓冲区的 API,这可能对代码的性能和组织都有好处。
FileChannel
也可以配置为非阻塞 IO,这对于最大化磁盘 I/O 很重要。
此外FileChannel
还提供用于零拷贝数据传输文件-文件、套接字文件、文件套接字的实用程序。
内存映射缓冲区
内存映射缓冲区是另一个 IO 选项,可通过FileChannel
.
理论上,内存映射对磁盘访问的开销最小,但在实践中使用的性能与FileChannel
.
内存映射缓冲区带来了一些问题:
- 内存映射的ByteBuffer只能由 GC 关闭,因此底层文件将在不可预知的时间内保持打开状态(在 Windows 中尤其痛苦)。
- 内存映射操作会导致页面错误,这会干扰 JVM 系统线程。因此,具有内存映射 IO 的应用程序会经常遇到 STW 停顿。
- 每个内存映射缓冲区限制为 2 GiB。因此需要管理多个缓冲区。这些缓冲区必须被重用,因为它们不能被显式关闭。
如果您正在使用类似 DB 的数据结构、难以预测访问模式并且希望依赖操作系统缓存而不是自己的缓冲区管理,那么内存映射缓冲区可能是一个不错的选择。
仍然提到的限制和缺乏性能优势使得内存映射 IO 在 Java 世界中非常小众的解决方案
推荐阅读
- scala - 设置覆盖标准
- leaflet - 在 geoJSON 功能上使用 getBounds
- amazon-web-services - 卡在 Nginx 索引页面上
- sharepoint - Sharepoint 自定义工作流程
- gitlab - 无法在集群上执行“helm install”。Tiller 由 gitab 安装
- c++ - C++ 只运行一段时间
- node.js - 安全访问渲染器进程中基于节点的模块
- angular - 拒绝在框架中显示“https://stackblitz.com/edit/zknwqv.run”,因为它将“X-Frame-Options”设置为“sameorigin”
- java - 如何在卡片布局下的面板中添加功能性 Java 键侦听器?
- python - 如何修复 ImportError:在 INSTALLED_APPS 中作为“apps.comments”存在时,没有名为 comments.models 的模块?