确定适当的缓冲区大小

8
我正在使用ByteBuffer.allocateDirect()来分配一些缓冲内存,以将文件读入内存,然后将该文件的字节进行哈希处理并得到文件哈希值(SHA)。输入文件的大小范围很大,从几KB到几GB不等。
我已经阅读了几个线程和页面(甚至在SO上),涉及选择缓冲区大小的问题。有人建议尝试选择本机FileSystem使用的缓冲区大小,以试图最小化读取操作的部分块等机会。例如,缓冲区为4100字节,而NTFS默认为4096字节,所以额外的4位需要单独的读取操作,非常浪费资源。
因此,坚持使用2的幂次方,如1024、2048、4096、8192等。我看到一些人推荐使用32KB的缓冲区,另一些人则建议将缓冲区的大小设置为输入文件的大小(对于小文件可能很好,但大文件呢?)。
坚持使用本机块大小的缓冲区有多重要?现代的SATA驱动器或更好的驱动器至少具有8MB的缓存,并且有其他现代操作系统的“魔法”来优化I/O,那么缓冲区大小有多关键,我应该如何确定我的缓冲区大小?我可以静态设置缓冲区大小,也可以动态确定。感谢您的任何见解。

唯一的方法是测试。请注意,适用于一台计算机的最佳方案可能不适用于另一台计算机。制作或下载一些不同大小的文件并进行读取。看看需要多长时间。 - Lee Meador
可能是 https://dev59.com/QnVC5IYBdhLWcg3wnCj6 的重复问题。 - Ben Barkay
@LeeMeador 测试的问题在于文件输入大小完全未知。 - SnakeDoc
只需使用各种大小的代表性文件,范围应在您预期的范围内,并在多个文件中平均每秒字节数。例如,3-300 MB可能是一个有趣的范围。或者100K到10 Gb。您的猜测足以进行估算。 - Lee Meador
1个回答

6
为了回答你的问题:(1)文件系统倾向于使用2的幂,因此您需要做相同的事情。(2)您的工作缓冲区越大,任何错误大小的影响就越小。
正如您所说,如果您分配了4100个字节并且实际块大小为4096个字节,则需要两次读取才能填满缓冲区。如果您有一个1000000个字节的缓冲区,那么高低一块都无关紧要(因为需要245个4096字节块才能填满该缓冲区)。此外,更大的缓冲区意味着操作系统有更好的机会排序读取。
话虽如此,我不会用NIO来做这件事。相反,我会使用简单的BufferedInputStream,并为我的read()使用1k缓冲区。
NIO的主要好处是将数据保留在Java堆之外。例如,如果您正在读写文件,则使用 InputStream 意味着操作系统将数据读入JVM管理的缓冲区中,JVM将其复制到堆上缓冲区中,然后再次复制到堆外缓冲区中,然后操作系统读取该堆外缓冲区以写入实际的磁盘块(通常添加自己的缓冲区)。在这种情况下,NIO将消除本机堆副本。

但是,要计算哈希值,您需要将数据保留在Java堆中,而 Mac SPI 将把它移动到那里。因此,您无法获得NBI将数据保留在堆外的好处,并且在我看来,“旧IO”更容易编写。

只需不要忘记, InputStream.read()不能保证读取您请求的所有字节。


嗯...我刚刚花了一些时间重构我的哈希方法/算法以实现更高的性能。请参见此线程:https://dev59.com/dXHYa4cB1Zd3GeqPGwhE -- 向下滚动到我的最新更新以查看我的当前方法 -- OP中的第一种方法是我的原始方法,它非常有效,但我开始优化/微调它,因为哈希在我正在处理的项目中非常重要。 - SnakeDoc
1
@SnakeDoc - 看了你的另一个问题,我发现你将缓冲区大小增加到了8K。如果在第一个(InputStream)版本中使用类似大小的缓冲区,性能会如何改变呢? - parsifal
1
但是,考虑到您的ByteBuffer代码看起来合理,我会转向使用更大的缓冲区的想法,以允许操作系统进行大量的顺序读取。我不知道您是否会从中获得巨大的性能提升,但正如一些评论者所说,只有通过反复测试才能知道。 - parsifal
1
@SnakeDoc - 我不确定你是否应该尝试隔离操作系统和磁盘驱动器,因为它们会影响你的生产时间。如果可以的话,请在测试中复制您的生产环境(在我看来,正确设置操作系统和内存大小将是最大的因素,驱动器类型则不太重要,除非您正在比较SAN和SSD)。对于测试,请尝试多次运行相同的程序,并尝试交错运行您的程序。 - parsifal
1
最后,决定缓存是否重要。如果您在生产中不断处理新文件,则缓存将使重复的测试运行比实际快。这里有一个页面列出了一些清除缓存的方法(我记不清您使用Linux还是Windows,但我使用Linux,所以我会寻找它):http://www.commandlinefu.com/commands/view/1026/empty-the-linux-buffer-cache - parsifal
显示剩余2条评论

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