2

我有這樣一段代碼在Android中,這是造成GC的海量日誌下面在android中導致大量垃圾收集的嵌套循環?

// 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 

感謝

+0

您創建了'4096^2'對象 - 您真的在使用它們嗎?不要忘記你正在使用內存有限的手機! – alfasin

+0

那麼你真正的問題是什麼?到目前爲止,唯一可能的答案是*「是 - 這是代碼的預期行爲」*。 –

+0

當我註釋掉「results [times] = FFT.fft(complex);」 GC日誌已停止。 複數的FFT是一個非常繁重的操作? –

回答

0

你的問題是,在Java,Complex是一個堆分配的Java對象。我相信它是不可變的,因此必須爲每個計算創建新的Complex實例。這使得複雜數字的工作數學非常緩慢並且分配了大量的內存。因此應儘可能避免。

純Java中的唯一解決方案是不使用內置的Complex類型,而是直接在成對的double陣列上進行FFT,每個陣列對應於實部和虛部。或者,可以使用包含實部和虛部的單個陣列,儘管對this question的評論意味着第一種方法傾向於提供更好的性能。缺少非堆分配對象是JVM的一個不幸的限制。

對於更高的性能,最好的方法是使用本地庫。一種選擇是FFTS,它是BSD許可的並且帶有JNI綁定。它使用運行時代碼生成和SIMD指令來實現比任何純Java庫更高的性能。