用Java映射大于2GB的文件

11

如何在Java中实现一个 byte[] get(offset, length) 方法以读取大于2GB的内存映射文件?

背景:

我正在尝试使用随机I/O高效地读取大于2GB的文件。当然,这个想法是使用Java nio和内存映射API。

问题出现在内存映射的2GB限制上。解决方案之一是将多个2GB的页面进行映射,并通过偏移索引。

这里有一个类似的解决方案:

在Java中对已排序的(内存映射?)文件执行二进制搜索

这个解决方案的问题在于它设计用于读取字节,而我的API应该读取byte[](所以我的API会像这样:read(offset, length))。

如果将最终的get()更改为get(offset, length),会发生什么呢?当我要读取的byte[]位于两个页面之间时会发生什么?

1个回答

4
不,我的回答二分搜索在排序(内存映射?)中无法将get()更改为get(offset, length),因为像您怀疑的那样,存在内存映射文件数组边界问题。我可以看到两种可能的解决方案:
  1. 重叠内存映射文件。当进行读取时,选择紧接在读取开始字节之前的起始字节的内存映射文件。这种方法对于大于最大内存映射大小50%的读取将不起作用。
  2. 创建一个从两个不同的内存映射文件中读取的字节数组创建方法。我不喜欢这种方法,因为我认为某些性能提升将会丢失,因为生成的数组将不是内存映射的。

1
哪些性能收益会丢失?如果你返回一个 byte[],那么你无论如何都要从 mmap() 区域复制。调用两次 System.arraycopy 而不是一次,对于相同数量的字节来说并没有太大的影响。 - Scott Lamb
@Scott Lamb:我同意,在“二分查找”算法中可能需要从两个不同的映射中读取时,get()的性能损失对于那些可能很少出现的边缘条件来说是可以忽略的。我的回答是说您需要编写代码来解决这个问题,因此有两种选择。仅添加偏移量而没有新代码支持get()将导致像索引超出边界等硬错误。 - Stu Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接