繁体   English   中英

Java中的循环语句垃圾回收

[英]Garbage Collection of Looping statements in Java

如今,我参加了Codegolf的一些比赛。 对于特定问题。 我已经在Java中提交了一个答案,其中包含这样的嵌套循环。

for(int i=0; i < 20_00_00_000; i++){
    for(int j=0; j < 10_00_000; j++){
        //declare some variables
        //do operations
        //modify variables outside of for loop
    }
}

假设这需要n次时间。

另一位成员发表了类似的答案,但像这样。

for(int i=0; i < 20_00_00_000; i++){
    nextLoop(pass necessary args);
}

private void nextLoop(necessary args){
    for(int j=0; j < 10_00_000; j++){
        //declare some variables
        //do operations
        //modify variables outside of for loop
    }
}

但这仅需要n次的60%。 然后我意识到这将与嵌套循环的Garbase集合有关。 两种代码的逻辑相同,但是将内部循环分成一种方法可以使其更快。 我认为这是因为nextLoop()方法完成后会发生垃圾回收,但是垃圾回收中存在与First代码嵌套的for循环有关的问题。

现在关于第一个代码,一旦父循环的下一次迭代开始,内部for循环占用的内存是否不会自动垃圾回收?

实码

方法2(更快)

public class MinPrimeFactorSum {

    static int[] primes = new int[20_000_000];
    static int count = 0;

    static int temp;
    static int p;
    static long total = 2;

    public static void main(String[] args) {

        long start = System.nanoTime();

        int i=3;
        for(; i<1_00_00_000; i += 2) {
            // Calling the inner loop as a method
            temp = getData(i);
            if( i == temp ) {
                primes[count] = temp;
                count++;
            }
            total += temp + 2;
        }
        System.out.println( --i + ": " + total + " in " + (System.nanoTime() - start)/1000000 + " milliseconds" );
    }

    // Inner Loop as a method
    private static int getData(int i) {
        temp = i;
        for(int index = 0;index < count; index++ ) {
            p = primes[index];
            if( i % p == 0 ) {
                temp = p;
                break;
            }
            if( p > Math.sqrt(i) ) {
                break;
            }
        }
        return temp;
    }

}

方法1(较慢)

public class MinPrimeFactorSum {

    static int[] primes = new int[20_000_000];
    static int count = 0;

    static int temp;
    static int p;
    static long total = 2;

    public static void main(String[] args) {

        long start = System.nanoTime();

        int i=3;
        for(; i<1_00_00_000; i += 2) {
            temp = i;

            // Inner Loop Starts
            for(int index = 0;index < count; index++ ) {
                p = primes[index];
                if( i % p == 0 ) {
                    temp = p;
                    break;
                }
                if( p > Math.sqrt(i) ) {
                    break;
                }
            }
            // Inner Loop ends

            if( i == temp ) {
                primes[count] = temp;
                count++;
            }
            total += temp + 2;
        }
        System.out.println( --i + ": " + total + " in " + (System.nanoTime() - start)/1000000 + " milliseconds" );
    }

}

经过一系列测试后,我才发布了这个问题。

较慢的代码使用静态温度,而较快的代码在函数内部声明一个本地温度。

要使两者相等,请尝试替换行temp = i; int temp = i; 然后再次测量。

编辑:我注意到您的评论,您已经使它们都使用了静态温度,并且调用该方法的版本仍然更快。 我认为差异是由于JIT造成的:它可能比优化内联版本更早地优化了方法(然后内联了)。 同样,您的基准测试方法也太简单了。 对Java代码进行基准测试非常棘手。 例如,请参阅Robust Java Benchmarking(IBM技术库)以获得对该主题的良好处理。

顺便说一下,在我的情况下,两种情况之间的时序差异仅为0.5%(3585 vs 3595 ms)。 当我优化您的代码时(通过将对Math.sqrt的调用移到循环外),它的运行速度快一倍以上,并且区别更加明显(1577与1687)。 (这是在32位Windows Core 2 Quad Q8200上。)

是的,不会在第二个循环的第一个循环内存中进行垃圾回收。 未被收集的原因是依赖关系,第一个循环中的第二个循环对第一个循环具有依赖性。因此,第二个循环中的事物取决于第一个循环中的事物,它们彼此之间是不完整的,但在第二种情况下,两个循环是独立的,一个循环不依赖于第二个循环,这就是为什么要进行垃圾回收的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM