内存映射文件的性能/稳定性 - Native或MappedByteBuffer - 与普通的'FileOutputStream相比

noa*_*hlz 11 java performance file-io java-native-interface production

我支持使用平面文件(纯文本)进行持久化的旧Java应用程序.由于应用程序的性质,这些文件的大小可以达到每天100s MB,并且应用程序性能的限制因素通常是文件IO.目前,该应用程序使用普通的'java.io.FileOutputStream将数据写入磁盘.

最近,我们有几个开发人员声称使用内存映射文件,在本机代码(C/C++)中实现并通过JNI访问,将提供更高的性能.但是,FileOutputStream已经为其核心方法使用本机方法(即write(byte [])),因此在没有硬数据或至少是轶事证据的情况下,它看起来很脆弱.

我有几个问题:

  1. 这种断言真的如此吗? 与Java的FileOutputStream相比,内存映射文件是否总能提供更快的IO?

  2. 从FileChannel访问的MappedByteBuffer类是否提供与通过JNI访问的本机内存映射文件库相同的功能?什么是MappedByteBuffer缺乏可能导致您使用JNI解决方案?

  3. 在生产应用程序中将内存映射文件用于磁盘IO有哪些风险?也就是说,具有连续正常运行时间且重启次数最少的应用程序(每月一次,最多).来自生产应用程序(Java或其他)的真实轶事是首选.

问题#3是很重要的-我可以回答这个问题,我自己部分通过写一个"玩具"的应用程序,使用逆足IO上述各种选项,测试,但通过张贴到,所以我希望能为现实世界的趣闻轶事/数据来啃.

[编辑]澄清 - 每天操作,应用程序创建多个文件,大小从100MB到1Gig.总的来说,应用程序可能每天写出多个数据.

Tom*_*ine 5

内存映射I/O不会使您的磁盘运行得更快(!).对于线性访问,它似乎有点无意义.

NIO映射缓冲区是真实的(关于任何合理实现的常见警告).

与其他NIO直接分配的缓冲区一样,缓冲区不是正常的内存,也不会有效地获得GCed.如果您创建了许多这些内容,您可能会发现内存/地址空间不足而不会耗尽Java堆.这显然是长时间运行过程的担忧.


Gar*_*ary 4

通过检查写入期间数据的缓冲方式,您也许可以加快速度。这往往是特定于应用程序的,因为您需要了解预期的数据写入模式。如果数据一致性很重要,那么这里就需要进行权衡。

如果您只是从应用程序将新数据写入磁盘,内存映射 I/O 可能不会有太大帮助。我不认为您有任何理由愿意在某些自定义编码的本机解决方案上投入时间。从您到目前为止所提供的内容来看,这对于您的应用程序来说似乎太复杂了。

如果您确定确实需要更好的 I/O 性能 - 或者在您的情况下仅需要 O 性能,我会研究硬件解决方案,例如调整的磁盘阵列。从业务角度来看,投入更多硬件来解决问题通常比花时间优化软件更具成本效益。它通常实施起来更快并且更可靠。

总的来说,软件的过度优化存在很多陷阱。您将为您的应用程序引入新类型的问题。您可能会遇到内存问题/GC 抖动,这会导致更多的维护/调整。最糟糕的是,其中许多问题在投入生产之前很难进行测试。

如果这是我的应用程序,我可能会坚持使用 FileOutputStream 以及一些可能调整的缓冲。之后,我将使用历史悠久的解决方案,即向其投入更多硬件。