当前文件格式
如果数字表示为Strings,则没有更快的方法来读取和解析它们,磁盘 I/O 将比 CPU 正在执行的任何操作慢几个数量级。唯一能做的就是使用具有巨大缓冲区大小的BufferedReader,并在使用Scanner 之前尝试尽可能多地获取内存中的文件。
替代文件格式
如果您可以在文件中将它们表示为二进制文件并使用DataInputStream class 读取数字,那么您可能会在 I/O 时间和 CPU 上略微减少,因为您不需要将String 表示解析为int,除非您的输入文件为数百兆字节或更大,否则这可能无法测量。 **缓冲输入流仍然比其他任何东西都更有效果,在这种情况下使用BufferedInputStream。
如何优化
您需要可靠的分析来检测您所做的任何更改是正面还是负面影响性能。
如果您一遍又一遍地读取同一个文件,操作系统磁盘缓存之类的东西会扭曲基准测试,操作系统会缓存它并搞砸您的基准测试。尽早了解什么是足够好。
“我们应该忘记小
效率,说大约 97%
时间:过早优化是
万恶之根”——Donald Knuth
Kunth 引用的过早部分是重要的部分,它的意思是:
不要在没有分析和基准的情况下进行优化,以验证您所做的更改实际上是一个瓶颈,并且您可以衡量更改的积极或消极影响。
Here is a quick benchmark 比较读取同一组二进制数的BufferedInputStream 与由BufferedReader 支持的Scanner 读取同一组数字作为带有SPACE 分隔符的文本表示。
结果非常一致:
在配备 8GB RAM 的 Core i3 笔记本电脑上处理 1,000 个号码
Read binary file in 0001 ms
Read text file in 0041 ms
在配备 8GB RAM 的 Core i3 笔记本电脑上处理 1,000,000 个号码
Read binary file in 0603 ms
Read text file in 1509 ms
在配备 8GB RAM 的 Core i3 笔记本电脑上处理 50,000,000 个号码
Read binary file in 29020 ms
Read text file in 70346 ms
50,000,000 个号码的文件大小如下:
48M input.dat
419M input.txt
在数字集变得非常大之前,读取二进制文件的速度要快得多。二进制编码整数上的 I/O 更少(大约 10 倍),没有 String 解析逻辑,以及对象创建的其他开销以及 Scanner 所做的任何其他事情。我继续使用Buffered 版本的InputStream 和Reader 类,因为这些是最佳实践,应尽可能使用。
对于额外的功劳,压缩将进一步减少大文件上的 I/O 等待,而对 CPU 时间几乎没有可测量的影响。