【问题标题】:Is there a performance advantage in writing a long file sequentially using MappedByteBuffer over a plain FileChannel?在普通 FileChannel 上使用 MappedByteBuffer 顺序写入长文件是否有性能优势?
【发布时间】:2012-09-28 05:36:58
【问题描述】:
我试图了解使用 16k 缓冲区短时间连续调用 FileChannel.write 和映射多个附加大小为 16k 的 ByteBuffer 之间的区别,如下所述:https://stackoverflow.com/a/7367952/962872
我认为映射字节缓冲区方法会产生大量垃圾,因为您在每次追加后丢弃 MappedByteBuffers。而且我也不确定它是否更快。而且你仍然需要做一堆映射操作......(每个附加一个)。
或者也许您应该映射一个巨大的 ByteBuffer(尽可能大)并继续写入这个 MappedByteBuffer?
我正在使用带有 Java 端 16kb 缓冲区的 FileChannel.write 方法作为写入文件的“快速”方式,但我想确保我不会丢失更快/更好的东西。
任何人都可以解释一下吗?
【问题讨论】:
标签:
java
performance
file-io
real-time
nio
【解决方案1】:
我认为映射字节缓冲区方法会产生大量垃圾,因为您在每次追加后丢弃 MappedByteBuffers。
如果您创建了 16 KB 的缓冲区,就会出现这种情况。如果您创建了 1 GB 的缓冲区,则不需要那么多缓冲区,并且这样做几乎不会造成任何损失(假设您有 64 位 JVM)
我正在使用带有 Java 端 16kb 缓冲区的 FileChannel.write 方法作为写入文件的“快速”方式,但我想确保我不会丢失更快/更好的东西。
我会检查您的写入速度是否已经超过驱动器的写入速度。内存映射文件给您的主要优势是更低的典型延迟。您可以写入的吞吐量将受到驱动器速度的限制。如果你有一个典型的 SSD,你的 CPU 仍然可以比它消耗的速度更快地写出数据,如果你使用 HDD,你做什么可能并不重要,因为驱动器要慢得多。
典型的写入吞吐量
- 现代 CPU:2,000 - 6,000 MB/秒
- SSD:300 - 1,200 MB/秒
- 磁盘控制器:200 - 600 MB/秒
- 硬盘:20 -60 MB/秒。
通常当 CPU 不是瓶颈时,您在软件中所做的事情对应用程序的性能影响不大。
就延迟而言,典型的延迟
- FileChannel.write():10 - 40 微秒,但可以达到 1 毫秒以上。
- 写入内存映射文件:短消息需要 100 纳秒,但在需要新的内存映射时可能会达到 100 毫秒。
【解决方案2】:
如果它存在的话,我怀疑它是否重要。我通过 MappedByteBuffers 测量输入,它只快 20%,不足以保证任何代码更改。通过 MappedByteBuffers 输出的代码更改要广泛得多,因为您必须做出特殊安排来扩展文件,这反过来又会带来内存不足的风险。
【解决方案3】:
IO 通常是瓶颈,或者是内存问题(缓存错误,但如果你必须重新分配,那也没有问题)。
我会尽可能简单地编写代码。然后,如果性能确实是一个问题,那么无论如何都要尝试替代方案(关于内存性能的 if 和异常太多)。您可能已经这样做了。