Kha*_*uti 6 java algorithm lambda overriding time-complexity
我有这段代码,我想知道第一个输入和第二个输入的执行时间之间存在差异的原因。我认为它应该花费相同的时间,因为我正在调用相同的方法,但它在两个对象中不执行任何操作。但是 input1 (这是 2 个实例的交替)在我的计算机上花费了 5 秒。input2(这是两个实例之间的任意选择)在我的计算机上花费了 17 秒。
public class Program {
private static final Runnable FIRST_INSTANCE = () -> {};
private static final Runnable SECOND_INSTANCE = () -> {};
private static Runnable[] input1() {
Runnable[] array = new Runnable[10000];
for (int i = 0; i < array.length; i++) {
array[i] = i % 2 == 0 ? FIRST_INSTANCE : SECOND_INSTANCE;
}
return array;
}
private static Runnable[] input2() {
Random rnd = new Random(0);
Runnable[] array = new Runnable[10000];
for (int i = 0; i < array.length; i++) {
array[i] = rnd.nextBoolean() ? FIRST_INSTANCE : SECOND_INSTANCE;
}
return array;
}
public static void main(String[] args) {
Runnable[] input1 = input1();
Runnable[] input2 = input2();
solve(input1);
solve(input2);
}
private static void solve(Runnable[] array) {
long start = System.nanoTime();
for (int j = 0; j < 500000; j++) {
for (Runnable r : array) {
r.run();
}
}
System.out.println((System.nanoTime() - start) / 1000000000.0);
}
}
Run Code Online (Sandbox Code Playgroud)
我认为这与缓存无关,因为它们使用相同的实例,并且这不是首先调用哪个的问题,因为我尝试在 input1 之前调用 input2 并且得到相同的结果(input2 总是较慢)。
某种编译器优化正在发挥作用。
我已经用 50000 次迭代而不是 500000 次尝试了你的代码,因为寿命很短。我的时间比你的快大约 10 倍。
首先,我运行了你的代码
0.502928476
1.68480928
Run Code Online (Sandbox Code Playgroud)
然后我尝试运行相同的命令-Djava.compiler=NONE(禁用 JIT):
25.267888581
24.742234792
Run Code Online (Sandbox Code Playgroud)
请注意时机变得多么糟糕。JIT 在这里绝对是一个嫌疑人。
然后我尝试变得input1不那么统一:
array[i] = i % 21 == 0 ? FIRST_INSTANCE : SECOND_INSTANCE;
但这并没有产生什么影响。然后我尝试从以下位置删除该模式input1:
array[i] = (int)(Math.sqrt(i) * Math.sqrt(i)) == i ? FIRST_INSTANCE : SECOND_INSTANCE;
0.973357599
1.82497641
Run Code Online (Sandbox Code Playgroud)
性能input1几乎差了一倍。
所以我的结论如下:出于某种原因,数组的一致性对 JIT 很重要:)
再进一步看一下:
input如果我们根本不运行,而是运行input25 次而不是两次,我们会得到:
1.826676411
1.835746098
1.566231165
1.531194014
1.551068832
Run Code Online (Sandbox Code Playgroud)
因此,JIT 似乎在第三个循环中完全启动了。请注意,时间约为 1.5 秒。
现在,如果我们开始运行input1两次,然后继续input2:
input1: 2 times
0.507165973
0.509543633
input2: 5 times
1.270496255 <------ WAT?
1.817742481
1.804664757
1.845583904
1.846861045
Run Code Online (Sandbox Code Playgroud)
看起来 JIT 的设置input1确实帮助了input2很多人,但后来被抛弃了,再也没有完全恢复过来