2012-12-16 77 views
0

使用Mapped FileChannel读取文件似乎闪电般快......但我想知道他们是怎么做到的?java映射FileChannel实现

他们只是在一个大的(〜64kB)缓冲区中读取数据,然后让我通过这个缓冲区行进?或者还有更多吗?

我对速度印象深刻,并希望更好地理解背后的算法。

+0

这通常是因为你的OS” MMAP功能的支持:http://en.wikipedia.org/wiki/Mmap – jackrabbit

回答

1

内存映射,将文件映射到您的内存中,Java提供了一个库来包装它,以便您可以相对安全地访问它。

它的优点包括:

  • 那里只有一个内存拷贝,在操作系统磁盘高速缓存,并在您的应用程序(一个或多个)内存。
  • 您可以在没有系统调用的情况下访问文件的随机区域。
  • Java确实限制了您可以映射的内容数量。例如,如果最大堆为1 GB,并且最大直接内存为1 GB,则仍然可以映射1 TB。

它的缺点包括:

  • 它消耗它不给回来,如果你重新映射或关闭文件虚拟内存。如果你有一个64位的JVM,这不是一个问题,但如果你有一个可能只有1 GB空闲的32位JVM,那么这个问题就非常有限。它在GC运行时释放虚拟内存。
  • 它每次读取/写入页面的最小数量。如果您有很多随机访问,但是如果您正在读/写多个磁盘上的文件,实际上会减慢顺序访问,这可能很好。随机附加多个文件一次4KB可能会导致高度碎片文件,这是不明智的。
  • 使用内存映射文件可能会更困难,使用普通的DataXxxxStream或BufferedReader/Writer。

我已经写了一对夫妇制作存储库的映射文件更容易使用,我会说,当超低延迟是至关重要的,我会用它,或者你需要阅读大量的内存,你想到会已经在磁盘缓存中,并且希望充分利用磁盘缓存。

值得注意的是,内存映射不会使磁盘子系统更快,如果这是限制因素,读/写数据的方式无关紧要。

+0

从Java文档:映射的字节缓冲区和它所代表仍然有效,直到缓冲区本身是文件映射垃圾回收。你确定它从不给回虚拟内存吗? – blackuprise

+0

@blackuprise你是对的。当不需要资源时,GC将释放映射。 –

+0

嗨,你介意分享你的实现吗? – Siavash

2

他们没有读取任何东西,直到你做了,那么你读的一块基本上是通过OS分页系统读取。打开可能会花费你几乎没有什么,但重复读取文件的相同部分可能会导致重复的I/O。什么都没有免费。