Java中下载文件时的合适缓冲区大小

9

使用Java传输大文件(3-4 GB)时,无论是上传还是下载,合理的缓冲区大小是多少?

byte buf[] = new byte[1024]

或者
byte buf[] = new byte[5 * 1024 * 1024]

有时候,即使您使用了一个大缓冲区并将其传递给read(byte array[])方法,这也不能保证您会获得完整的5MB缓冲区。在我的测试中,我观察到每个read()调用的平均大小通常为1.5KB。从性能角度来看,这是否合理?如果有人能指向一些更详细讨论此问题的资源,我将不胜感激。

2个回答

10

看起来你正在读取网络连接(TCP?)

1500字节是默认的以太网MTU,这就解释了为什么每次读取通常只能获得1.5KB。通过配置网络栈使用jumbo frames,MTU通常可以增加到9KB。

因此,几乎肯定没有必要使buf大于9KB。使用较小的缓冲区(比如1KB以上)可能会对性能产生负面影响也可能不会。

无论如何,获取确定答案的唯一方法是通过对不同缓冲区大小进行基准测试。


嗯,很好的观点。我还没有考虑到TCP栈的MTU。 - LordDoskias
1
使用更大的缓冲区将减少Java代码和本地代码之间的切换次数,并可能对性能产生影响,而与网络数据包大小无关。 - jarnbjo
实际上,如果您正在使用IPv6,您可能也会遇到IPv6的巨型帧,这些帧最大可达4GB(尽管您今天不会使用如此大的帧;但请记住,在IPv4中,巨型帧并不是真正的标准,因此我相信您也可能在那里找到更大的帧)。所以,如果这确实是一个值得担心的问题,我不会将其硬编码。据我所知,Java SDK类的IO缓冲区默认为8kb。 - Voo
我在本地网络中尝试了Android设备的缓冲区大小。我发现1024(好/最佳),4096(好),16384(平均)。而8k是最差的。 - shantanu

1
在我的研究和测试中,使用Java 6在Linux上从套接字读取时,8K是最佳缓冲区大小。如果分配的缓冲区大于8K,那么它将只是浪费空间。我曾经读到过Java使用的本地调用使用8K缓冲区,这就是为什么8K是最佳的原因,但我已经找不到参考资料了。有一个指向这个事实的错误,但这并不是确凿的证据: http://bugs.sun.com/view_bug.do?bug_id=6444633 话虽如此,尝试在你感兴趣的平台上进行实验,你会找到最佳的缓冲区大小。如果你懒得实验,8K是一个很好的默认值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接