This does not look trivial, specially for a read/write buffered FileChannel. Is there anything opensource implemented somewhere that I can base my implementation on?
To be clear for those who did not understand:
FileChannel does buffereing in the OS level and I want to do buffering in the Java level. Read here to understand: FileChannel#force and buffering
@Peter I want to write a huge file to disk from a fast message stream. Buffering and batching are the way to go. So I want to batch in Java and then call FileChannel.write.
I recommend using a
BufferedOutputStream
wrapping aFileOutputStream
. I do not believe you will see any performance improvement by mucking withByteBuffer
andFileChannel
, and that you'll be left with a lot of hard-to-maintain code if you go that route.The reasoning is quite simple: regardless of the approach you take, the steps involved are the same:
ByteBuffer
(and yes, you want a direct buffer), you're still moving the bytes. You will make more JNI calls with theByteBuffer
, but that's a marginal cost.fwrite
, a kernel call that copies bytes from the C heap into a kernel-maintained disk buffer.There may be a few microseconds gained or lost depending on exactly how you implement these steps, but you can't change the basic steps.
The
FileChannel
does give you the option to callforce()
, to ensure that step #5 actually happens. This is likely to actually decrease your overall performance, as the underlyingfsync
call will not return until the bytes are written. And if you really want to do it, you can always get the channel from the underlying stream.Bottom line: I'm willing to bet that you're actually IO-bound, and there's no cure for that save better hardware.
I would have two threads, the producer thread produces ByteBuffers and appends them to the tail a queue, the consumer thread remove some ByteBuffers from the head of the queue each time, and call fileChannel.write(ByteBuffer[]).
FileChannel only works with ByteBuffers so it is naturally buffered. If you need additional buffering to can copy data from ByteBuffer to ByteBuffer but I am not sure why you would want to.
FileChannel does tell the OS what to do. The OS usually has a disk cache but FileChannel has no idea whether this is the case or not.
You are in luck, because you don't have a choice. ;) This is the only option.