在JAVA中的嵌套for循环中,为什么小循环中的大循环比大循环中的小循环快?
当迭代次数相同时,我想知道外部“for循环”的较小迭代是否更快 这是我的java代码 循环迭代总数为1000亿次在JAVA中的嵌套for循环中,为什么小循环中的大循环比大循环中的小循环快?,java,performance,for-loop,nested,Java,Performance,For Loop,Nested,当迭代次数相同时,我想知道外部“for循环”的较小迭代是否更快 这是我的java代码 循环迭代总数为1000亿次 public class Test { public static long run1() { final long start = System.nanoTime(); long cnt = 0; for(int i = 0; i<1000000000; i++) { for(int j = 0
public class Test {
public static long run1() {
final long start = System.nanoTime();
long cnt = 0;
for(int i = 0; i<1000000000; i++) {
for(int j = 0 ; j<100 ; j++) {
cnt++;
}
}
final long end = System.nanoTime();
System.out.println("run1 : "+(end-start)*1e-9+" sec");
return start - end;
}
public static long run2() {
final long start = System.nanoTime();
long cnt = 0;
for(int i = 0; i<100; i++) {
for(int j = 0 ; j<1000000000 ; j++) {
cnt++;
}
}
final long end = System.nanoTime();
System.out.println("run2 : "+(end-start)*1e-9+" sec");
return start - end;
}
public static void main(String[] args) {
for(int i = 0 ; i < 10 ; i++) {
long test1 = run1();
long test2 = run2();
System.out.println("Time diff : "+(test1-test2)*1e-9+" sec\n");
}
}
}
像这样,
我想知道为什么会有这些结果
并且,通过三重嵌套循环编辑,得到了类似的结果。简单的回答是:JIT和你的数学是错误的 让我们从run方法开始,它以这一行和一个返回结束
System.out.println("run1 : "+(end-start)*1e-9+" sec");
return start - end;
这里的问题是打印结束-开始,然后返回开始-结束。我没有在run方法中进行数学运算,而是将其转换为每次运行只负责运行和计时:
public class loops
{
public static long run1()
{
final long start = System.nanoTime();
long cnt = 0;
for (int i = 0; i < 1000000000; i++)
{
for (int j = 0; j < 100; j++)
{
cnt++;
}
}
final long end = System.nanoTime();
return end - start;
}
public static long run2()
{
final long start = System.nanoTime();
long cnt = 0;
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 1000000000; j++)
{
cnt++;
}
}
final long end = System.nanoTime();
return end - start;
}
public static void main(String[] args)
{
for (int i = 0; i < 10; i++)
{
long test1 = run1();
long test2 = run2();
System.out.println("run1 : " + test1 + " ns");
System.out.println("run2 : " + test2 + " ns");
System.out.println("Time diff : " + (test1 - test2) + " ns\n");
}
}
}
公共类循环
{
公共静态长运行1()
{
最终长启动=System.nanoTime();
长cnt=0;
对于(int i=0;i<100000000;i++)
{
对于(int j=0;j<100;j++)
{
cnt++;
}
}
最终长端=System.nanoTime();
返回结束-开始;
}
公共静态长运行2()
{
最终长启动=System.nanoTime();
长cnt=0;
对于(int i=0;i<100;i++)
{
对于(int j=0;j<100000000;j++)
{
cnt++;
}
}
最终长端=System.nanoTime();
返回结束-开始;
}
公共静态void main(字符串[]args)
{
对于(int i=0;i<10;i++)
{
长test1=run1();
长test2=run2();
System.out.println(“run1:+test1+ns”);
System.out.println(“run2:+test2+ns”);
System.out.println(“时间差:+(test1-test2)+“ns\n”);
}
}
}
我还把数学题去掉了,因为。。那么,为什么要麻烦呢?将这些值视为纳秒有什么不对?这才是真正的
运行此命令,可以看到初始大值减小并接近零。在一些运行中,这两个版本甚至都达到了零
零纳秒?是的,即时计算。让量子计算去吸它吧!
好吧,这不是即时的。当您检查以下各项时,则不会:
该方法提供纳秒精度,但不一定
纳秒分辨率(即值更改的频率)
它只是比可行的测量速度快,因为JIT可能最终发现该方法实际上什么都不做。现在,为什么一种方法比另一种方法减少得更快,需要深入研究JIT,以及它如何决定优化一种方法和另一种方法,这是我所不知道的
最后,两者几乎没有区别。两种方法初始运行后,最大的时间差最多只有几毫秒。我不认为说一个版本比另一个版本快有什么意义
有趣的旁注:
JDK-11的性能似乎不太好。。。
格拉尔文的表现似乎不太好。。。虽然,可能有一些标志可以改善它。。。
简单的回答是:JIT和你的数学是错误的 让我们从run方法开始,它以这一行和一个返回结束
System.out.println("run1 : "+(end-start)*1e-9+" sec");
return start - end;
这里的问题是打印结束-开始,然后返回开始-结束。我没有在run方法中进行数学运算,而是将其转换为每次运行只负责运行和计时:
public class loops
{
public static long run1()
{
final long start = System.nanoTime();
long cnt = 0;
for (int i = 0; i < 1000000000; i++)
{
for (int j = 0; j < 100; j++)
{
cnt++;
}
}
final long end = System.nanoTime();
return end - start;
}
public static long run2()
{
final long start = System.nanoTime();
long cnt = 0;
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 1000000000; j++)
{
cnt++;
}
}
final long end = System.nanoTime();
return end - start;
}
public static void main(String[] args)
{
for (int i = 0; i < 10; i++)
{
long test1 = run1();
long test2 = run2();
System.out.println("run1 : " + test1 + " ns");
System.out.println("run2 : " + test2 + " ns");
System.out.println("Time diff : " + (test1 - test2) + " ns\n");
}
}
}
公共类循环
{
公共静态长运行1()
{
最终长启动=System.nanoTime();
长cnt=0;
对于(int i=0;i<100000000;i++)
{
对于(int j=0;j<100;j++)
{
cnt++;
}
}
最终长端=System.nanoTime();
返回结束-开始;
}
公共静态长运行2()
{
最终长启动=System.nanoTime();
长cnt=0;
对于(int i=0;i<100;i++)
{
对于(int j=0;j<100000000;j++)
{
cnt++;
}
}
最终长端=System.nanoTime();
返回结束-开始;
}
公共静态void main(字符串[]args)
{
对于(int i=0;i<10;i++)
{
长test1=run1();
长test2=run2();
System.out.println(“run1:+test1+ns”);
System.out.println(“run2:+test2+ns”);
System.out.println(“时间差:+(test1-test2)+“ns\n”);
}
}
}
我还把数学题去掉了,因为。。那么,为什么要麻烦呢?将这些值视为纳秒有什么不对?这才是真正的
运行此命令,可以看到初始大值减小并接近零。在一些运行中,这两个版本甚至都达到了零
零纳秒?是的,即时计算。让量子计算去吸它吧!
好吧,这不是即时的。当您检查以下各项时,则不会:
该方法提供纳秒精度,但不一定
纳秒分辨率(即值更改的频率)
它只是比可行的测量速度快,因为JIT可能最终发现该方法实际上什么都不做。现在,为什么一种方法比另一种方法减少得更快,需要深入研究JIT,以及它如何决定优化一种方法和另一种方法,这是我所不知道的
最后,两者几乎没有区别。两种方法初始运行后,最大的时间差最多只有几毫秒。我不认为说一个版本比另一个版本快有什么意义
有趣的旁注:
JDK-11的性能似乎不太好。。。
格拉尔文的表现似乎不太好。。。虽然,可能有一些标志可以改善它。。。
您看到的性能差异是由于循环展开,JVM首先展开内部循环,但无法展开外部循环 展开意味着:
for (int i=0;i<MAX;i++) cnt++;
您看到的性能差异是由于循环展开,JVM首先展开内部循环,但无法展开外部循环 展开
run1: 1000000000 * (100 / 16 + 4) = 10 000 000 000 operations
run2: 100 * (1000000000 / 16) = 6 250 000 000 operations