当前位置: 首页 > 面试题库 >

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

洪景铄
2023-03-14
问题内容

我有一个从文件创建MessageDigest(哈希)的方法,我需要对很多文件(> = 100,000)执行此操作。为了使性能最大化,我应该为读取文件设置多大的缓冲区?

大多数人都熟悉基本代码(以防万一,在此重复):

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();

最大化吞吐量的理想缓冲区大小是多少?我知道这是与系统有关的,并且我很确定它与操作系统,文件系统和 HDD有关,并且可能还有其他硬件/软件。

(我应该指出,我是Java的新手,所以这可能只是一些我不知道的Java API调用。)

编辑:我不提前知道将要使用的系统种类,所以我不能承担很多。(出于这个原因,我使用Java。)

编辑:上面的代码缺少try..catch之类的东西,以使帖子更小


问题答案:

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

大多数文件系统配置为使用4096或8192的块大小。理论上,如果配置缓冲区大小,以便读取的内容比磁盘块多几个字节,则文件系统的操作效率极低(即配置您的缓冲区一次读取4100字节,每次读取将需要文件系统进行2次块读取)。如果块已经在缓存中,那么您就要付出RAM-> L3 / L2缓存延迟的代价。如果您不走运,并且块尚未在缓存中,那么您还要付出磁盘-> RAM延迟的代价。

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

现在,在典型的流传输方案中,这可以抵消很多,因为从磁盘读取的块将在您下一次读取时仍在内存中(毕竟,我们在这里进行顺序读取)-这样就结束了在下一次读取时为RAM-> L3 / L2缓存延迟时间付出代价,而不是磁盘-> RAM延迟。就数量级而言,磁盘-> RAM延迟是如此之慢,以至于几乎淹没了您可能要处理的任何其他延迟。

因此,我怀疑如果您使用不同的缓存大小运行测试(我自己没有做过),您可能会发现缓存大小(取决于文件系统块的大小)的影响很大。除此之外,我怀疑情况会很快趋于平稳。

有一吨的条件和例外这里-系统的实际上是相当惊人的复杂性(刚开手柄上的L3 - >二级缓存传输是一种精神令人难以置信的复杂,它与每一个CPU类型的变化)。

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



 类似资料:
  • 问题内容: 在编写用于OpenGL库的Matrix类时,我遇到了一个问题,即使用Java数组还是使用Buffer策略存储数据(JOGL为Matrix操作提供直接缓冲区复制)。为了对此进行分析,我编写了一个小型性能测试程序,该程序比较了Arrays vs Buffers和Direct Buffers上循环和批量操作的相对速度。 我想在这里与您分享我的结果(因为我发现它们很有趣)。请随时发表评论和/或

  • 本文向大家介绍在Python中打开文件时如何指定缓冲区大小?,包括了在Python中打开文件时如何指定缓冲区大小?的使用技巧和注意事项,需要的朋友参考一下 如果看一下open-open(name [,mode [,buffering]])的函数定义,您会发现在Python 2中它需要3个参数,第三个是缓冲。可选的buffering参数指定文件所需的缓冲区大小:0表示未缓冲,1表示行缓冲,任何其他正

  • 我正在使用JOGL,但这个问题一般适用于OpenGL。似乎存在类似的问题,但它们要么针对GLSL代码,要么与复制帧缓冲区的内容有关,要么是一般建议-使用帧缓冲区对象,而不是。 我正在做一些阴影映射。如何使用帧缓冲对象将深度通道直接渲染到纹理? 能否请你贴一段初始化纹理和帧缓冲对象的代码,以及渲染场景前初始化一切的代码? 目前,我使用<code>glCopyTexSubImage2D<code>。我

  • 我想在我的小libgdx游戏中使用框架缓冲区。 游戏使用了,我修改了s摄像头,使其使用50宽31高的视口。然后我将的投影矩阵设置为。这样做,我有一个分辨率独立的游戏,我可以使用我自己的“世界单位”,而不是使用像素。 但是现在,如果我创建一个,我必须给它一个大小。我必须给它摄像机视口的大小还是屏幕的大小(以像素为单位)? 而且,当我渲染的东西,我可以渲染他们在,这意味着渲染在几乎在游戏窗口的中间?

  • 本文向大家介绍vim 管理缓冲区,包括了vim 管理缓冲区的使用技巧和注意事项,需要的朋友参考一下 示例 您可以使用缓冲区来处理多个文件。当您使用打开文件时 它会在一个新的缓冲区中打开(该命令意味着编辑文件)。保存文件临时副本的新缓冲区。 您可以使用转到上一个缓冲区,使用进入:bp[rev]下一个缓冲区:bn[ext]。 您可以转到b{n}第n个缓冲区。b2转到第二个缓冲区。 使用:ls或:buf

  • 问题内容: Linux的默认套接字缓冲区大小是多少?有什么命令可以看到吗? 问题答案: 如果要在终端中查看缓冲区大小,可以看一下: (供阅读) (写) 它们包含三个数字,分别是最小,默认和最大内存大小值(以字节为单位)。