嵌套循环导致android中的大量垃圾收集?
Posted
技术标签:
【中文标题】嵌套循环导致android中的大量垃圾收集?【英文标题】:Nested loop causing massive Garbage collection in android? 【发布时间】:2014-02-06 06:46:58 【问题描述】:我在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
提前致谢
【问题讨论】:
您创建了4096^2
对象——您真的使用了所有这些对象吗?不要忘记您使用的是内存有限的手机!
那么您的实际问题是什么?到目前为止,唯一可能的答案是“是的 - 这是此类代码的预期行为”。
当我注释掉“results[times] = FFT.fft(complex);”这一行时GC 日志已停止。复数的 FFT 是不是很繁重的运算?
当我在我的程序中执行循环时,这个确切的 gc 确实有类似的问题,你找到解决方案了吗?
不,我开始认为在 Android 手机中对复数执行 FFT 是一项繁重的操作,并且会占用大量内存。
【参考方案1】:
您的问题是,在 Java 中,Complex
是一个堆分配的 Java 对象。我相信它是不可变的,因此必须为每次计算创建新的Complex
实例。这使得对复数进行数学运算变得极其缓慢并分配了大量内存。因此应尽可能避免。
纯 Java 中唯一的解决方案是不使用内置的 Complex
类型,而是直接对成对的 double
数组进行 FFT,实部和虚部各一个。或者,可以使用包含实部和虚部的单个数组,尽管this question 的 cmets 暗示第一种方法往往会提供更好的性能。缺乏非堆分配对象是 JVM 的一个不幸限制。
要获得更高的性能,最好的方法是使用本机库。一种选择是FFTS,它是 BSD 许可的并带有 JNI 绑定。它使用运行时代码生成和 SIMD 指令来实现远高于任何纯 Java 库的性能。
【讨论】:
以上是关于嵌套循环导致android中的大量垃圾收集?的主要内容,如果未能解决你的问题,请参考以下文章