没有JIT优化

3

看一下这个问题 :

代码:

class test
{
    public static void main(String abc[])
    {
        for( int k=1; k<=3; k++)
        {
            for( int N=1; N<=1_000_000_000; N=N*10)
            {
                long t1 = System.nanoTime();

                int j=1;
                for(int i=0; i<=N; i++)
                    j=j*i;

                long t2 = System.nanoTime() - t1;
                System.out.println("Time taken for "+ N + " : "+ t2);
            }
        }
    }
}

以上代码的输出:
Time taken for 1 : 2160
Time taken for 10 : 1142
Time taken for 100 : 2651
Time taken for 1000 : 19453
Time taken for 10000 : 407754
Time taken for 100000 : 4648124
Time taken for 1000000 : 12859417
Time taken for 10000000 : 13706643
Time taken for 100000000 : 136928177
Time taken for 1000000000 : 1368847843
Time taken for 1 : 264
Time taken for 10 : 233
Time taken for 100 : 332
Time taken for 1000 : 1562
Time taken for 10000 : 17341
Time taken for 100000 : 136869
Time taken for 1000000 : 1366934
Time taken for 10000000 : 13689017
Time taken for 100000000 : 136887869
Time taken for 1000000000 : 1368178175
Time taken for 1 : 231
Time taken for 10 : 242
Time taken for 100 : 328
Time taken for 1000 : 1551
Time taken for 10000 : 13854
Time taken for 100000 : 136850
Time taken for 1000000 : 1366919
Time taken for 10000000 : 13692465
Time taken for 100000000 : 136833634
Time taken for 1000000000 : 1368862705

在循环中,即使i的值从0开始,表示产品为零,也没有JIT优化。为什么呢? 在上面提供的链接中,我之前将for循环放在方法调用中,JIT正在进行优化。将语句放在方法中是否有助于优化过程?

这个问题感觉不太实际。你在做一些无用的事情 - JIT 优化对于一个真正的代码来说真的很重要吗? - Jon Skeet
你正在以纳秒为单位测量时间,因此速度足够快。在这里查看以毫秒为单位的修改测试 - http://ideone.com/Xq0xj1 - Sri Harsha Chilakapati
2个回答

5
  1. 在您之前的问题中,JIT编译器优化了start方法的完整代码,而没有分析在方法返回时变量中存在什么数字。这是因为您选择将方法设置为void,给JIT编译器一个简单明了的线索,表明计算出的任何值都将被丢弃。

  2. 与您之前的示例相比,当前示例没有调用void方法,自然不会发生优化。为什么没有其他可帮助这种完全不同情况的优化,这是一个无法回答的问题。在您测试代码的特定JVM实现和特定JVM调用中,就不存在这样的优化。


2

循环本身会被JIT编译(通过第二次和第三次执行的略微较低的运行时间可以观察到),但是消除整个循环只有在方法本身被多次执行时才会完成,因为只有这样JIT才有足够的运行时信息来确保它可以真正地消除它而不产生后果。

如果我更改您的代码,则在第三次调用时将消除该循环:

public class LoopJit2 {

    public static void main(String abc[]) {
        for (int x = 0; x < 3; x++) {
            loopMethod();
        }
    }

    private static void loopMethod() {
        for (int N = 1; N <= 1_000_000_000; N = N * 10) {
            long t1 = System.nanoTime();

            int j = 1;
            for (int i = 0; i <= N; i++)
                j = j * i;

            long t2 = System.nanoTime() - t1;
            System.out.println("Time taken for " + N + " : " + t2);
        }
    }
}

时间序列:

Time taken for 1 : 1466
Time taken for 10 : 1467
Time taken for 100 : 2934
Time taken for 1000 : 20044
Time taken for 10000 : 201422
Time taken for 100000 : 1993200
Time taken for 1000000 : 4038223
Time taken for 10000000 : 11182357
Time taken for 100000000 : 111290192
Time taken for 1000000000 : 1038002176
Time taken for 1 : 1466
Time taken for 10 : 1467
Time taken for 100 : 2934
Time taken for 1000 : 20044
Time taken for 10000 : 10755
Time taken for 100000 : 124667
Time taken for 1000000 : 1010045
Time taken for 10000000 : 10201156
Time taken for 100000000 : 103184413
Time taken for 1000000000 : 1019723107
Time taken for 1 : 978
Time taken for 10 : 1467
Time taken for 100 : 1467
Time taken for 1000 : 1955
Time taken for 10000 : 978
Time taken for 100000 : 489
Time taken for 1000000 : 977
Time taken for 10000000 : 977
Time taken for 100000000 : 978
Time taken for 1000000000 : 978

根据您的结果,似乎即使原始代码也应该通过堆栈替换进行优化。也许只是需要更长时间? - Marko Topolnik
@MarkoTopolnik 我也尝试了原始代码,使用更大的迭代次数,我的猜测是它首先需要运行+ jit整个方法至少一次,然后才能得出结论并安全地进行优化。 - Mark Rotteveel
3
我认为按照每个方法单独实现JIT编译/优化比试图在方法内的任意块中这样做要更可行。因此,这也是为什么应该尝试将功能分解为较小的方法并由其他方法调用的论点。这使得JIT可以独立地优化每个方法。 - Simon Lehmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接