首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在使用FileInputStream时,如何确定理想的缓冲区大小?

在使用FileInputStream时,如何确定理想的缓冲区大小?
EN

Stack Overflow用户
提问于 2008-10-25 19:13:52
回答 9查看 120.3K关注 0票数 168

我有一个从文件创建MessageDigest (散列)的方法,我需要对许多文件(>= 100,000)执行此操作。为了最大限度地提高性能,我应该设置多大的缓冲区来读取文件?

几乎每个人都熟悉基本的代码(为了以防万一,我在这里重复一下):

代码语言:javascript
复制
MessageDigest md = MessageDigest.getInstance( "SHA" );
FileInputStream ios = new FileInputStream( "myfile.bmp" );
byte[] buffer = new byte[4 * 1024]; // what should this value be?
int read = 0;
while( ( read = ios.read( buffer ) ) > 0 )
    md.update( buffer, 0, read );
ios.close();
md.digest();

要最大化吞吐量,理想的缓冲区大小是多少?我知道这是依赖于系统的,我非常确定它依赖于操作系统、FileSystem和硬盘,而且可能还有其他的硬件/软件。

(我应该指出的是,我对Java比较陌生,所以这可能只是一些我不知道的Java API调用。)

编辑:我事先不知道这将被用在什么样的系统上,所以我不能假设很多。(我之所以使用Java就是因为这个原因。)

编辑:上面的代码缺少了像try..catch这样的东西来使帖子更小

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2008-10-26 03:44:21

最佳缓冲区大小与许多因素有关:文件系统块大小、CPU缓存大小和缓存延迟。

大多数文件系统配置为使用块大小为4096或8192的文件系统。理论上,如果您将缓冲区大小配置为读取比磁盘块多几个字节,则文件系统的操作效率可能会非常低(即,如果您将缓冲区配置为一次读取4100字节,则每次读取将需要文件系统读取两个块)。如果数据块已经在缓存中,那么您最终将付出内存-> L3/L2缓存延迟的代价。如果你不走运,数据块还没有在缓存中,那么你也要付出磁盘的代价-->RAM延迟。

这就是为什么您看到大多数缓冲区的大小是2的幂,并且通常大于(或等于)磁盘块大小。这意味着您的一个流读取可能会导致多个磁盘块读取-但这些读取将始终使用完整的块-没有浪费的读取。

现在,在典型的数据流方案中,这会被抵消相当多,因为当您点击下一次读取时,从磁盘读取的数据块仍将在内存中(毕竟,我们在这里进行顺序读取)-因此,您最终会在下一次读取时支付内存-> L3/L2缓存延迟价格,而不是磁盘->内存延迟。就数量级而言,disk->RAM延迟是如此缓慢,以至于它几乎淹没了您可能正在处理的任何其他延迟。

因此,我怀疑如果您使用不同的缓存大小运行测试(我自己还没有这样做),您可能会发现缓存大小对文件系统块的大小有很大的影响。除此之外,我怀疑情况很快就会稳定下来。

这里有大量的条件和例外-系统的复杂性实际上是相当惊人的(仅仅是获得L3 -> L2缓存传输的句柄就是令人难以置信的复杂,而且它随着每种CPU类型的不同而变化)。

这就引出了“现实世界”的答案:如果你的应用程序有99%的使用率,将缓存大小设置为8192,然后继续前进(更好的是,选择封装而不是性能,并使用BufferedInputStream来隐藏细节)。如果您属于1%的高度依赖磁盘吞吐量的应用程序,请精心设计您的实现,以便您可以交换不同的磁盘交互策略,并提供旋钮和转盘,以允许您的用户测试和优化(或提出一些自我优化的系统)。

票数 226
EN

Stack Overflow用户

发布于 2008-10-25 19:21:21

是的,它可能依赖于不同的东西--但我怀疑它会有多大的不同。我倾向于选择16K或32K作为内存使用和性能之间的良好平衡。

请注意,您应该在代码中使用try/finally块,以确保即使抛出异常,也会关闭流。

票数 21
EN

Stack Overflow用户

发布于 2008-10-25 20:49:47

在大多数情况下,这真的无关紧要。只需选择一个合适的大小,如4K或16K,并坚持使用它。如果您确信这是应用程序中的瓶颈,那么您应该开始分析以找到最佳的缓冲区大小。如果您选择的大小太小,您将浪费时间进行额外的I/O操作和额外的函数调用。如果您选择的大小太大,您将开始看到许多缓存未命中,这将真正减慢您的速度。不要使用比L2缓存大小更大的缓冲区。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/236861

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档