确定合适的缓冲区大小(Determining Appropriate Buffer Size)

2019-08-31 10:16发布

我使用ByteBuffer.allocateDirect()分配一些缓冲存储器中读取文件到内存中,然后最终散列的文件字节数和获取文件的散列(SHA)出来。 输入文件规模大小不一,从几KB的几个GB的任何地方。

我看过几个线程和关于选择的缓冲区大小的页面(甚至一些在SO)。 一些建议试图选择与本地文件系统,企图minimalize读取操作的机会,对部分块等使用一个。 如4100个字节,NTFS默认为4096,所以额外的4个比特缓冲器将需要一个单独的读出操作,是非常浪费的。

因此,与我见过一些推荐的2,1024,2048,4096,8192,等列强坚持缓冲器32KB的大小,以及其他建议缓冲区输入文件的大小(也许还不错,对于小文件,但什么关于大文件?)。

如何重要的是它坚持到本机块大小的缓冲区? 现代化的演讲(上驱动器高速缓存假设现代SATA驱动器或更好地与至少8MB,和其他现代操作系统的“神奇”来优化I / O)是多么重要的缓冲区的大小,我应该如何最佳地确定什么大小矿井设置为? 我可以静态设置,或者动态地确定呢? 感谢您的任何见解。

Answer 1:

要回答你直接问:(1)文件系统往往使用2的幂,所以你想要做的一样。 (2)较大的工作缓冲区,较少影响的任何错误大小都会有。

正如你所说,如果分配4100和实际块大小为4096,则需要两次读取填充缓冲区。 相反,如果你有1,000,000字节的缓冲区,然后是一块高或低都无所谓(因为它需要245 4096字节的块,以填补该缓冲区)。 此外,较大的缓冲装置,该操作系统具有更好的机会来订购读取。

这就是说,我不会用NIO这一点。 相反,我会使用一个简单BufferedInputStream ,与我也许1K缓冲区read()秒。

NIO的主要好处是保持数据出Java堆。 如果你正在读,写文件,例如,使用InputStream意味着该操作系统将数据读入一个JVM管理缓冲区,JVM将复制到一间堆缓冲区,然后再复制到一个离堆缓冲器,则OS读取离堆缓冲区中的写入实际的磁盘块(并且通常将其自身的缓冲器)。 在这种情况下,NIO将消除机堆副本。

然而,要计算散列,你需要有Java堆中的数据,和Mac SPI 将它有移动 。 所以,你没有得到NBI的保持数据的离堆利益,以及IMO“老IO”更容易编写。

但不要忘记, InputStream.read() 不能保证阅读所有你要求的字节数。



文章来源: Determining Appropriate Buffer Size