使用 ByteBuffer 在通道上进行 I/O 操作 - 性能比较
我想使用 ByteBuffer 在通道上执行 I/O 操作。最后我想出了三种解决方案:
FileChannel inChannel = new FileInputStream("input.txt").getChannel();
FileChannel outChannel = new FileOutputStream("output.txt").getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024 * 1024);
方法一:使用 hasRemaining()
while (inChannel.read(buf) != -1) {
buf.flip();
while (buf.hasRemaining()) {
outChannel.write(buf);
}
buf.clear();
}
方法二:使用 compact()
while (inChannel.read(buf) != -1 || buf.position() > 0) {
buf.flip();
outChannel.write(buf);
buf.compact();
}
方法三:混合模型
while (inChannel.read(buf) != -1) {
buf.flip();
outChannel.write(buf);
buf.compact();
}
// final flush of pending output
while (buf.hasRemaining())
outChannel.write(buf);
问题是:哪种方法最多性能和吞吐量?
I want to perform I/O operation on channels using ByteBuffer
. Finally I came up with three solutions:
FileChannel inChannel = new FileInputStream("input.txt").getChannel();
FileChannel outChannel = new FileOutputStream("output.txt").getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024 * 1024);
Method 1: using hasRemaining()
while (inChannel.read(buf) != -1) {
buf.flip();
while (buf.hasRemaining()) {
outChannel.write(buf);
}
buf.clear();
}
Method 2: using compact()
while (inChannel.read(buf) != -1 || buf.position() > 0) {
buf.flip();
outChannel.write(buf);
buf.compact();
}
Method 3: hybrid model
while (inChannel.read(buf) != -1) {
buf.flip();
outChannel.write(buf);
buf.compact();
}
// final flush of pending output
while (buf.hasRemaining())
outChannel.write(buf);
The question is: Which method has the most performance and throughput?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为什么要使用compact()? - 可能涉及重复复制大量数据。
如果您没有充分的理由在写入所有先前读取的数据之前执行另一次读取,则第一种方法是可行的方法。
哦,顺便说一句:如果您只想将数据从一个文件复制到另一个文件,请查看
transferTo()
或transferFrom()
。这是最高效的文件复制方式,因为这可能使用底层操作系统的非常高效的操作,例如 DMA。(编辑:transferTo()等当然不需要需要任何ByteBuffer,混合了两种想法:))
Why would you want to use
compact()
at all? - It may involve copying of a lot of data repeatedly.Your 1st method is the way to go if you don't have serious reason to perform another read before all of the previously read data is written.
Oh, and by the way: If you're only out for copying data from one file to another have a look at
transferTo()
, ortransferFrom()
. This is the most performant way for file copy as this may use very efficient operations of the underlying OS, like DMA, for instance.(Edit: transferTo() etc. do of course not need any ByteBuffer, mixed two thoughts there :))
为了最大限度地提高性能,我建议您尝试使用大约 32 KB 的直接缓冲区。根据您的系统,16 KB 到 64 KB 的大小通常效果最佳。
对于文件通道,它应该能够每次读取/写入所有数据,所以我认为各种方法不会有任何区别。然而,在读取/写入套接字通道时,它可能会产生影响。
To maximise performance I suggest you try a direct buffer which is about 32 KB. This sizes of 16 KB to 64 KB often work best depending on your system.
For file channels it should be able to read/write all the data every time, so I don't think the various methods will make any difference. It can make a difference when reading/writing to Socket Channels however.