在 READ_WRITE 模式下使用大量 MappedByteBuffer 会减慢 Windows 7 的速度

Posted

技术标签:

【中文标题】在 READ_WRITE 模式下使用大量 MappedByteBuffer 会减慢 Windows 7 的速度【英文标题】:Using lots of MappedByteBuffer's in READ_WRITE mode slows down Windows 7 to a crawl 【发布时间】:2012-09-24 20:08:44 【问题描述】:

我正在尝试在 READ_WRITE 模式下使用 Java MappedByteBuffers 来映射一个大文件(数十 GB)或一组大量小文件(~128MB)。这是为了实现高性能的 B 树。

我的问题是,在配备 8GB RAM 和 JDK 7 的 Windows 7 笔记本电脑上,一切正常,直到物理内存已满并且操作系统开始实际将数据写入文件。此时,Windows 会慢下来。 I/O 似乎完全饿死了任何其他活动。鼠标指针几乎不能移动,我通常最终不得不强制重启机器。

以下代码演示了该问题:

public static void testMap() throws Exception

    MappedByteBuffer[] mbbs = new MappedByteBuffer[512];
    for (int i = 0; i < 512; i++)
    
        System.out.printf("i=%d%n", i);
        RandomAccessFile raf = new RandomAccessFile(String.format("D:/testMap.%d.bin", i), "rw");
        mbbs[i] = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 128*1024*1024);
        for (int j = 0; j < 128*1024; j++) 
            mbbs[i].put(j*1024, (byte)(i*j));
        
    

我不介意 I/O 是否需要一些时间。过了一会儿,操作系统实际上必须开始将字节写入文件。但是,在这里,该过程实际上使整个操作系统处于饥饿状态。我怎样才能避免这种情况?

【问题讨论】:

重要的是要认识到在使用稀缺资源时会有资源限制。您是否有理由同时需要 512 个可用的开放内存映射文件?根据您的用例,您可能会采用多种不同的方法,包括汇集稀缺资源(打开文件句柄)。 实际上,我希望这些文件几乎可以随机访问。这就是为什么我希望能够同时映射所有视图。这似乎被接受为一种好的做法,当然在 64 位机器上。例如,请参阅***.com/questions/9261316/…。它确实适用于阅读,但不完全适用于写作。我怀疑一段时间后,来自任何进程的任何内存访问都会迫使操作系统换出 JVM 进程加载的一些脏页。有什么建议可以避免这种情况吗? 根据您希望同时访问的文件数量,池化解决方案的效果会相当好。使用池化方法,您可以通过改变池大小来调整性能。无论如何,当系统内存不足时,操作系统将不得不开始交换。这就是整台机器爬行的原因。 【参考方案1】:

您正在映射 512x128x1024x1024 字节或 64 GB,而您有 8 GB。所以你实际上是过度使用了 8 倍的内存。这对于阅读来说是可以的,因为操作系统可以将你的页面错误到一个充满空值的页面,所有这些页面甚至可能是同一个页面。但是当你写的时候,页面必须虚拟存在。所以你在折腾。您需要 8 倍的主内存或

【讨论】:

感谢您的评论。我期待操作系统足够聪明,可以在整个系统崩溃之前换掉脏页。你看,我并没有过度使用内存:我不介意操作系统做大量的磁盘 IO,因为这个想法是操作系统应该比程序更好地管理它的缓存。顺便说一句,即使页面没有充满空值,映射也可以很好地读取(在我的代码中,几乎每个页面都包含一些非空字节)。操作系统只是触发 IO 并很好地管理缓存,这就是使用内存映射文件的重点。 @user1695431 根据定义,提交 10 倍的物理内存量是过度提交。 但是我不想把这个虚拟内存区域提交给物理内存。如果操作系统只是在程序写入页面时换出页面,我可以。我认为这是使用内存映射文件的优势之一:能够像访问内存一样访问文件,即使文件大于可用的物理内存。此外,它在阅读方面效果很好。所以,我仍在寻找一个令人满意的解决方案来解决我的问题......

以上是关于在 READ_WRITE 模式下使用大量 MappedByteBuffer 会减慢 Windows 7 的速度的主要内容,如果未能解决你的问题,请参考以下文章

在linux中如何替换文件中模式内的子模式

javascript MAPP

html 百事可乐:MAPP登陆页面

mapp

如何从哈希图中找到最高的键值

打开MASA Blazor的正确姿势4.1:母版页布局