1

This is more of a generic question which has to do with static variables and the process life cycle.

I have developed a heavy multi threaded signal processing Android app. It is targeted at API level 9 and above, and if I can it will restricted to only dual core devices. This is purely an academic App and not intended for the general user, and has been developed for teaching Digital Signal Processing. So for this reason I am calculating the DFT many times and so forth so there is quite a bit of computation and size allocation required.

I have declared a bunch of static float and double arrays which get used in static functions like in the example below. The complete code is is a bit to big to put here, so the example below just illustrates the idea.

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]);
                             }
         }
    }
}

The application is working great as it is. The problem lies in different execution times when say the function fillArrays() gets called. The first time the function is called it takes only 4 seconds to complete, however the second and each subsequent time it is run it takes closer to 30 seconds to complete. In log cat you can see that the heap size does increase drastically the second time, but every subsequent time it stays about the same. In MAT the two dimensional array 'spectrum' retains a large portion of heap. This is understandable as it would contain nfft*nsegs (512*560) sized data stored as doubles.

So I am not sure if the time taken is due to the Garbage collector or perhaps the interpreter going into each step of the for loops (strange tho if the first execution is still short). I thought maybe for all other arrays, setting them to non-static weakreferences so the garbage collector can clean them up, but it seems everything I try is to the same time effects. So the question is, when using large array objects what is the most effective way to allocate space for them. At the moment they are static, but are not final as the size changes frequently due to user preference. Any help would be great thanks.

  • Note this is just example code, calcSpec() gets called each time the user changes parameters or a new audio file is loaded to compute frequency data 'spectrum', then only after calcSpec is called, the user can call fillArrays(). In terms of profiling, I have been using MemoryAnalyzer and allocation tracker. The odd thing here the time increase is only in fillArrays(). The first execution it take 4seconds, the second (without calling calcSpec() again, so the same spectrum data is used again) it takes 30 seconds. In both Mat and allocation tracker the Retained size and allocation size are the same for every execution.
trincot
  • 317,000
  • 35
  • 244
  • 286
digiphd
  • 2,319
  • 3
  • 23
  • 22
  • I'm not seeing why calling `fillArrays` has anything to do with object allocation. Do you also call `calcSpec` a second time? Also, have you tried profiling the code to find out exactly where the time is going? Also use the allocation tracker to see what's eating memory. The allocation tracker is described [here](http://developer.android.com/resources/articles/track-mem.html). – Ted Hopp Nov 09 '11 at 04:27
  • I'm wondering if the garbage collector is picking an unfortunate moment to kick in. As an experiment, try calling `fillArrays` several times in sequence, measuring the time it takes each call. The variation in times might provide evidence for or against the gc being involved. As an aside, this code: `Math.pow(Math.abs(mag[i]), 2)` seems very inefficient; why not just use `mag[i] * mag[i]`? – Ted Hopp Nov 09 '11 at 05:51
  • Good move with the Math.pow function. I have been implementing exactly what you recommended, but also did it again after you suggested it. In terms of the GC, it seems to be freeing allot of heap space, on my Motorola atrix I get many logcat logs such as:-----> 11-09 16:19:28.553: DEBUG/dalvikvm(3184): GC_EXPLICIT freed 172K, 51% free 2850K/5767K, external 2377K/2773K, paused 42ms On the xoom I get: -----> 11-09 16:24:12.260: DEBUG/dalvikvm(8782): GC_EXPLICIT freed 4K, 9% free 7315K/8007K, paused 31ms+150ms – digiphd Nov 09 '11 at 06:28
  • For both the xoom and atrix the first execution of fillArrays() takes about 3-4 seconds, however on the atrix each subsequent execution takes only 20-30 seconds, where as the xoom it takes 40-50 seconds. Very strange. – digiphd Nov 09 '11 at 06:29
  • I don't see anything in the posted code that would explain this behavior. Perhaps something else in your code -- perhaps totally unrelated to these functions -- is generating lots of garbage? If it's practical, another experiment would be to call `System.gc()` just before each call to `fillArrays()`. See if that affects the time spent in `fillArrays()`. Also -- is there any reason that `nsegs` is a float? Since it's being used in the loop test, it would be faster if it were an int. – Ted Hopp Nov 09 '11 at 07:00
  • 1
    No need to wonder. When it's being slow, just *[pause it](http://stackoverflow.com/questions/375913/what-can-i-use-to-profile-c-code-in-linux/378024#378024) 2-3 times*. You'll see the problem. – Mike Dunlavey Nov 09 '11 at 18:59

0 Answers0