我正在测试 Java 中整数加法的性能。我这样做的方法是对数十亿个整数求和。我用来测试的示例文件是一个1G的二进制文件。我的程序非常简单,如下面的代码片段所示。
int result = 0;
FileChannel fileChannel = new FileInputStream(filename).getChannel();
long fileSize = fileChannel.size();
intBuffer = fileChannel.map(MapMode.READ_ONLY, startPosition, fileSize).asIntBuffer();
try {
while (true) {
result += intBuffer.get();
}
} catch (BufferUnderflowException e) {
System.out.println("Complete reading");
}
从上面可以看出,它只是在每个循环中执行了两个操作
- 从文件中读取整数
- 整数加法
这个程序在我的机器上运行了大约 2 分钟。我还通过将 result += intBuffer.get()
更改为 result = intBuffer.get()
(如以下代码片段所示)进行了另一次不添加的测试。
int result = 0;
FileChannel fileChannel = new FileInputStream(filename).getChannel();
long fileSize = fileChannel.size();
intBuffer = fileChannel.map(MapMode.READ_ONLY, startPosition, fileSize).asIntBuffer();
try {
while (true) {
result = intBuffer.get();
}
} catch (BufferUnderflowException e) {
System.out.println("Complete reading");
}
在这种情况下,整个程序在 1 秒内完成。与其上面的同级变体相比,与 IO 读取相比,整数加法似乎主导了 CPU 时间。
我写了另一个基准测试程序只是为了证明我的猜测,它做的加法次数与上面的例子相同。
int result = random.nextInt();
int other = random.nextInt();
int num = 1073741824 / 4;
while(num-- > 0) {
result += other;
}
在相同数量的整数加法加上整数增量运算的情况下,该程序完成不到 1 秒。
我的问题是
- 是什么导致了这些运行之间的主要时间差异? Java 编译器是否会优化最后一个?
如有任何想法,我们将不胜感激。
最佳答案
那是因为与 CPU 相比,磁盘 I/O 非常慢。
在第一种情况下,您正在从文件中读取数据。所以你受磁盘访问的约束。
在第二种情况下,它都在 CPU 中。
所以这与添加速度无关。
- 第一种情况受磁盘速度的限制。
- 第二种情况(可能)受限于随机数生成器的速度。
至于为什么result = intBuffer.get()
看起来很快:(摘自评论)
我能想到的两个可能的原因:
- Dead Code Elimination JIT 正在优化除最后一次迭代之外的所有迭代。
- I/O 缓冲:操作系统在第一次读取后将整个文件缓冲到内存中。*
*所以后面的pass会很快。通过重新排序测试或每次清除 I/O 缓存,很容易测试这种情况
关于java - Java中的整数加法性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9083736/