映射大小或限制如何影响MappedByteBuffer的性能?

3
我正在处理大文件,并使用MappedByteBuffer进行读写操作。由于我对它不太了解,所以有一些疑问。
MappedByteBuffer buf = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, offset, size);
1. 我知道ByteBuffer的限制是整数最大值,那么我应该如何设置MappedByteBuffer的大小?应该使用小块还是整数最大值? 当我增加映射大小时,我的应用程序的读写性能是否也会提高?
2. 当这个大小增加时,我同时的内存使用量也会增加吗?我之所以有这个疑问,是因为我需要创建多个文件进行读写。 如果一个文件分配了2GB的内存,而我有6个文件,那么我需要12GB内存,或者我的想法完全错误。
3. 这与JVM-Xmx还是我的物理内存有关吗?
这是我的用法:
    List<MappedByteBuffer> mappings = new ArrayList<MappedByteBuffer>();
    
    int mSize = 25;
    
    long MAPPING_SIZE = 1 << mSize;
    
    File file = File.createTempFile("test", ".dat");
    RandomAccessFile raf = new RandomAccessFile(file, "rw");
    ByteOrder byteOrder = java.nio.ByteOrder.nativeOrder(); // "LITTLE_ENDIAN";
    
    try {
        long size = 8L * width * height;          
        for (long offset = 0; offset < size; offset += MAPPING_SIZE) {
            long size2 = Math.min(size - offset, MAPPING_SIZE);
            MappedByteBuffer buf = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, offset, size2);
            buf.order(byteOrder);
            mappings.add(buf);
        }
    }

你应该使用更少但更大的缓冲区,而不是更多但更小的。 - user207421
2个回答

3
  1. 如果您知道您的文件大小要比2G大得多,那么简短的答案是肯定的。唯一的缺点是您的磁盘空间使用情况:如果您使用了一个较大的增量,则浪费的磁盘空间数量会更大,如果 size 不是 MAPPING_SIZE 的倍数。

  2. 只有您的虚拟内存使用量在增加。除非您使用的是32位机器,否则这不应该成为问题。在Linux上,最大虚拟内存为128TiB,因此您还有一些余地。如果您需要的虚拟内存超过了这个限制,您将需要选择另一种解决方案。内存映射文件使用页面高速缓存:操作系统只会在使用时一页一页地在物理内存中加载文件页面 [1],并在可用物理RAM变紧时卸载这些页面。

  3. 没有。请参见第2条。

以下是一些额外的资源,这是一个关于页面高速缓存如何工作的很好的总结: Page Cache, the Affair Between Memory and Files

[1]: 一个页面是一个操作系统级内存单位,通常为4KiB。


文件大小与2的幂次方有关吗?我使用2^30来映射大小,因为我不能使用2^31,filechannel会抛出大小异常,但我可以使用(2^31-1)。 - cgrgcn

1
关于第二点,您是正确的。 对于第三点,它与您的物理内存有关。 至于第一点,这取决于您的用例,但如果您使用 Integer.MAX_VALUE,您将会看到应用程序存在一些延迟。
使用 MappedByteBuffer,我们需要确保文件适合内存。否则,我们可能会填满整个内存,并因此遇到常见的 OutOfMemoryException 异常。我们可以通过仅加载文件的一部分来克服这个问题。
MappedByteBuffer 在 JVM 内存中创建虚拟内存映射。文件内容被加载到虚拟内存中,而不是堆中。
以下是几个链接,可帮助您更好地理解。
  1. http://www.tothenew.com/blog/handling-large-files-using-javanio-mappedbytebuffer/
  2. https://www.baeldung.com/java-mapped-byte-buffer

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