3

我试图了解使用 16k 缓冲区连续调用 FileChannel.write 和映射多个附加大小为 16k 的 ByteBuffer 之间的区别,如下所述:https ://stackoverflow.com/a/7367952/962872

我认为映射的字节缓冲区方法会在每次追加后丢弃 MappedByteBuffers 时产生大量垃圾。而且我也不确定它是否更快。而且你仍然需要做一堆映射操作......(每个附加一个)。

或者您应该映射一个巨大的 ByteBuffer(尽可能大)并继续写入这个 MappedByteBuffer?

我正在使用带有 Java 端 16kb 缓冲区的 FileChannel.write 方法作为写入文件的“快速”方式,但我想确保我不会丢失更快/更好的东西。

任何人都可以发光吗?

4

3 回答 3

3

我认为映射的字节缓冲区方法会在每次追加后丢弃 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 毫秒。
于 2012-09-28T07:31:24.563 回答
1

如果它存在的话,我怀疑它是否重要。我通过 MappedByteBuffers 测量输入,它只快 20%,不足以保证任何代码更改。通过 MappedByteBuffers 输出的代码更改要广泛得多,因为您必须做出特殊安排来扩展文件,这反过来又会带来内存不足的风险。

于 2012-09-28T07:42:41.030 回答
0

IO 通常是瓶颈,或者是内存问题(缓存错误,但如果您必须重新分配,那将没有问题)。

我会尽可能简单地对其进行编码。然后,如果性能确实是一个问题,那么无论如何都要尝试替代方案(关于内存性能的 if 和异常太多)。你可能已经这样做了。

于 2012-09-28T05:46:01.787 回答