大型静态浮点和双数组导致App减速

时间:2011-11-09 04:22:05

标签: android performance optimization double heap

这更像是一个与静态变量和流程生命周期有关的通用问题。

我开发了一款重型多线程信号处理Android应用。它的目标是API级别9及更高级别,如果可以,它将仅限于双核设备。这纯粹是一个学术应用程序,不适合一般用户,并且已经开发用于教授数字信号处理。因此,我正在多次计算DFT等等,因此需要进行相当多的计算和大小分配。

我已经声明了一堆静态float和double数组,它们在静态函数中使用,如下例所示。完整的代码放在这里有点大,所以下面的例子只是说明了这个想法。

public class SpecMod {
//Example of global static declarations
static double [][] spectrum = null;
static double [][] phaseMat = null;
static float [][] mframes = null;
static float [][] sframes = null;
static double []  mag = null;
static double [] Pxx = null;
static double [] GAMk = null;
static int nfft = 512;
static float nsegs = 560;
//Compute  FFT data



public static void calcSpec(int fs, float [] buffer, float f, float g){
     //Example of static array memory allocation
    sframes = new float[nlen][(int) nsegs];
    spectrum = new double[nfft][(int) nsegs];
    phaseMat = new double[nfft][(int) nsegs];
    mframes = new float[nlen][(int) nsegs];
    mag = new double[nfft];
    Pxx = new double[nfft];
    GAMk = new double[nfft];

    }

 public static void fillArrays(){
//Example of array manipulation 
        for (int j = 0; j < nsegs; j++) {

            for (int i = 0; i < nfft; i++) {
                mag[i] = spectrum[i][j];
                phase[i] = phaseMat[i][j];
                Pxx[i] = Math.pow(Math.abs(mag[i]), 2);

                GAMk[i] = (Pxx[i] / muPnn[i]);
                             }
         }
    }
}

应用程序工作正常。如果调用函数fillArrays(),则问题在于执行时间不同。第一次调用该函数时,它只需要4秒即可完成,但是第二次和每次运行它都需要接近30秒才能完成。在log cat中,您可以看到堆大小确实第二次大幅增加,但随后每次都保持大致相同。在MAT中,二维数组'spectrum'保留了很大一部分堆。这是可以理解的,因为它将包含存储为双精度的nfft * nsegs(512 * 560)大小的数据。

所以我不确定所花费的时间是由于垃圾收集器还是解释器进入for循环的每一步(如果第一次执行仍然很短,那就很奇怪)。我想也许对于所有其他数组,将它们设置为非静态弱引用,以便垃圾收集器可以清理它们,但似乎我尝试的一切都是同一时间效果。 所以问题是,当使用大型数组对象时,为它们分配空间的最有效方法是什么。目前它们是静态的,但由于用户偏好,尺寸经常变化,因此不是最终的。任何帮助都会非常感谢。

  • 请注意,这只是示例代码,每次用户更改参数或加载新的音频文件以计算频率数据'spectrum'时都会调用calcSpec(),然后只有在调用calcSpec之后,用户才能调用fillArrays() 。在分析方面,我一直在使用MemoryAnalyzer和分配跟踪器。这里奇怪的是时间增加仅在fillArrays()中。第一次执行需要4秒,第二次执行(不再调用calcSpec(),因此再次使用相同的频谱数据)需要30秒。在Mat和分配跟踪器中,保留大小和分配大小对于每次执行都是相同的。

0 个答案:

没有答案