这看起来并不简单,特别是对于读/写缓冲的 FileChannel。是否有任何开源实现了我可以基于我的实现的地方?
不懂的人说清楚:
FileChannel 在操作系统级别进行缓冲,我想在 Java 级别进行缓冲。阅读此处了解:FileChannel#force 和缓冲
@Peter我想从快速消息流中将一个大文件写入磁盘。缓冲和批处理是要走的路。所以我想在Java中批处理,然后调用FileChannel.write。
这看起来并不简单,特别是对于读/写缓冲的 FileChannel。是否有任何开源实现了我可以基于我的实现的地方?
不懂的人说清楚:
FileChannel 在操作系统级别进行缓冲,我想在 Java 级别进行缓冲。阅读此处了解:FileChannel#force 和缓冲
@Peter我想从快速消息流中将一个大文件写入磁盘。缓冲和批处理是要走的路。所以我想在Java中批处理,然后调用FileChannel.write。
我建议使用BufferedOutputStream
包装 a FileOutputStream
。我不相信你会通过使用and看到任何性能改进,如果你走这条路,你会留下很多难以维护的代码。ByteBuffer
FileChannel
推理非常简单:无论您采用哪种方法,所涉及的步骤都是相同的:
ByteBuffer
(是的,您想要一个直接缓冲区),您仍在移动字节。您将使用 进行更多的 JNI 调用ByteBuffer
,但这是边际成本。fwrite
,一个内核调用,将字节从 C 堆复制到内核维护的磁盘缓冲区中。根据您实施这些步骤的具体方式,可能会增加或减少几微秒,但您无法更改基本步骤。
FileChannel
确实为您提供了调用选项,force()
以确保步骤 #5 实际发生。这实际上可能会降低您的整体性能,因为在写入字节之前底层fsync
调用不会返回。如果你真的想这样做,你总是可以从底层流中获取通道。
底线:我敢打赌,您实际上是受 IO 限制的,并且无法治愈节省更好的硬件。
FileChannel 仅适用于 ByteBuffers,因此它是自然缓冲的。如果您需要额外的缓冲才能将数据从 ByteBuffer 复制到 ByteBuffer 但我不确定您为什么要这样做。
FileChannel 在操作系统级别进行缓冲
FileChannel 确实告诉操作系统该做什么。操作系统通常有一个磁盘缓存,但 FileChannel 不知道是否是这种情况。
我想在 Java 级别做缓冲
你很幸运,因为你别无选择。;) 这是唯一的选择。
我将有两个线程,生产者线程产生 ByteBuffers 并将它们附加到队列的尾部,消费者线程每次从队列的头部删除一些 ByteBuffers,并调用 fileChannel.write(ByteBuffer[])。