gpt4 book ai didi

java - 为什么这段 Java 代码的性能如此不一致?

转载 作者:太空宇宙 更新时间:2023-11-04 07:40:00 26 4
gpt4 key购买 nike

我正在运行一个小测试,尽管它是一个微型基准测试,但它确实很好地模仿了我们在生产中实际所做的事情。

我正在创建一个 2D 数组,包含 5 列和 10,000,000 行,其中填充了 0-19 之间的随机整数。然后,只要第二列中的值是偶数,我就想对第三列中的所有数字求和。我这样做 100 次来热身,然后再做 100 次并计时需要多长时间。

在我的机器上,绝大多数时间大约需要 9 秒,但有时只需要不到 6 秒。

它看起来不像垃圾收集或 JIT 编译。

有人知道为什么它偶尔会如此快吗?

我使用以下参数在 Linux 上使用 JDK7u11 运行代码:-server -XX:+PrintCompilation -Xms500m -Xmx500m -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails 但是,使用各种不同的 JDK(从 6 一直到 8)并删除所有这些参数似乎不会显着影响计时。

这是代码:

import java.util.ArrayList;
import java.util.Random;

public class JavaPerformanceTest {
public static void main(String[] args) {
int numColumns = 5;
int numRows = 10000000;
int[][] data = new int[numColumns][numRows];
Random rand = new Random(1234);
for (int j = 0; j < numColumns; j++) {
for (int i = 0; i < numRows; i++) {
data[j][i] = rand.nextInt(20);
}
}
int warmUp = 100;
ArrayList<Integer> sums = new ArrayList<Integer>();
System.out.println("warm up " + warmUp + " times");
long warmUpStart = System.nanoTime();
for (int i = 0; i < warmUp; i++) {
sums.add(sum(numRows, data));
}
long warmUpEnd = System.nanoTime();
System.out.println("warm up complete " + (warmUpEnd - warmUpStart) / 1000000);
int numberOfRuns = 100;
int finalSum = 0;
long startTime = System.nanoTime();
for (int i = 0; i < numberOfRuns; i++) {
finalSum = sum(numRows, data);
}
long endTime = System.nanoTime();
long diff = (endTime - startTime) / 1000000;
System.out.println("Time taken: " + diff + " Sum: " + finalSum);
}


public static int sum(int numRows, int[][] columnBased) {
int sum = 0;
for (int i = 0; i < numRows; i++) {
if ((columnBased[1][i] % 2) == 0) {
sum += columnBased[2][i];
}
}
return sum;
}
}

谢谢,尼克。

最佳答案

导致性能下降的可能原因有很多,包括缓存未命中和分支预测失败。我会确保您的代码是最佳的,然后重复它以确保结果稳定。

import java.util.ArrayList;
import java.util.Random;

public class JavaPerformanceTest {
public static void main(String[] args) {
int numColumns = 5;
int numRows = 10000000;
byte[][] data = new byte[numColumns][numRows];
Random rand = new Random(1234);
for (int j = 0; j < numColumns; j++) {
for (int i = 0; i < numRows; i++) {
data[j][i] = (byte) rand.nextInt(20);
}
}
int warmUp = 10;
ArrayList<Integer> sums = new ArrayList<Integer>();
System.out.println("warm up " + warmUp + " times");
long warmUpStart = System.nanoTime();
for (int i = 0; i < warmUp; i++) {
sums.add(sum(numRows, data));
}
long warmUpEnd = System.nanoTime();
System.out.println("warm up complete " + (warmUpEnd - warmUpStart) / 1000000);
for (int t = 0; t < 3; t++) {
int numberOfRuns = 100;
int finalSum = 0;
long startTime = System.nanoTime();
for (int i = 0; i < numberOfRuns; i++) {
finalSum = sum(numRows, data);
}
long endTime = System.nanoTime();
long diff = (endTime - startTime) / 1000000;
System.out.println("Time taken: " + diff + " Sum: " + finalSum);
}
}


public static int sum(int numRows, byte[][] columnBased) {
int sum = 0;
byte[] col1 = columnBased[1];
byte[] col2 = columnBased[2];
for (int i = 0; i < numRows; i++)
// use multiplication instead of "if" to avoid branch prediction failures
sum += ((col1[i] + 1) & 1) * col2[i];
return sum;
}
}

打印

warm up 10 times
warm up complete 109
Time taken: 1006 Sum: 47505460
Time taken: 1006 Sum: 47505460
Time taken: 1026 Sum: 47505460

总之:优化代码对性能的提升远远超过使用命令行参数。

关于java - 为什么这段 Java 代码的性能如此不一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16212654/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com