嵌套循环导致Android中的大量垃圾收集?

时间:2014-02-06 06:46:58

标签: java android memory-management garbage-collection nested-loops

我在android中有这段代码,导致GC的大量日志

    // When turning into frequency domain we'll need complex numbers:
    byte audio[] = out.toByteArray();  //approx size 827392
    int amountPossible = 200;
    Complex[][] results = new Complex[amountPossible][];

    // For all the chunks:
    for (int times = 0; times < amountPossible; times++) {
        Complex[] complex = new Complex[4096];
        for (int i = 0; i < 4096; i++) {
            // Put the time domain data into a complex number with imaginary
            // part as 0:
            complex[i] = new Complex(audio[(times * 4096) + i], 0);
        }
        // Perform FFT analysis on the chunk:
        results[times] = FFT.fft(complex);
    }

以下是几个日志

    D/dalvikvm(10602): GC_CONCURRENT freed 805K, 88% free 3911K/31075K, paused 2ms+5ms
     D/dalvikvm(10602): GC_CONCURRENT freed 1796K, 88% free 3957K/31075K, paused 1ms+2ms
     D/dalvikvm(10602): GC_CONCURRENT freed 1811K, 88% free 3970K/31075K, paused 1ms+3ms
    D/dalvikvm(10602): GC_CONCURRENT freed 1711K, 87% free 4102K/31075K, paused 2ms+3ms
    D/dalvikvm(10602): GC_CONCURRENT freed 1806K, 87% free 4138K/31075K, paused 1ms+3ms
    D/dalvikvm(10602): GC_CONCURRENT freed 1755K, 87% free 4226K/31075K, paused 1ms+3ms
    D/dalvikvm(10602): GC_CONCURRENT freed 1827K, 87% free 4242K/31075K, paused 1ms+3ms
    D/dalvikvm(10602): GC_CONCURRENT freed 1732K, 87% free 4258K/31075K, paused 2ms+2ms
    D/dalvikvm(10602): GC_CONCURRENT freed 1714K, 86% free 4387K/31075K, paused 1ms+3ms

提前致谢

1 个答案:

答案 0 :(得分:0)

您的问题是,在Java中,Complex是堆分配的Java对象。我相信它是不可变的,因此必须为每个计算创建新的Complex个实例。这使得复数上的数学运算非常慢并且分配了大量内存。因此应尽可能避免这种情况。

纯Java中唯一的解决方案是不使用内置的Complex类型,而是直接在成对的double数组上进行FFT,每个数组分别用于实部和虚部。或者,可以使用包含实部和虚部的单个数组,但this question的注释意味着第一种方法倾向于提供更好的性能。缺少非堆分配的对象是JVM的一个不幸的限制。

为了获得更高的性能,最好的方法是使用本机库。一个选项是FFTS,它是BSD许可的,并带有JNI绑定。它使用运行时代码生成和SIMD指令来实现远高于任何纯Java库的性能。