Большой статический float и двойные массивы, вызывающие замедление работы приложения - PullRequest
1 голос
/ 09 ноября 2011

Это более общий вопрос, касающийся статических переменных и жизненного цикла процесса.

Я разработал тяжелое многопоточное приложение для обработки сигналов Android. Он нацелен на уровень API 9 и выше, и, если смогу, будет ограничен только двухъядерными устройствами. Это чисто академическое приложение, которое не предназначено для обычного пользователя и было разработано для обучения цифровой обработке сигналов. Поэтому по этой причине я вычисляю DFT много раз и так далее, поэтому требуется довольно много вычислений и распределения размера.

Я объявил набор статических чисел с плавающей запятой и двойных массивов, которые используются в статических функциях, как в примере ниже. Полный код немного сложен, поэтому приведенный ниже пример просто иллюстрирует идею.

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 двумерный массив «спектр» сохраняет большую часть кучи. Это понятно, так как в нем содержатся данные размером nfft * nsegs (512 * 560), хранящиеся в виде двойных чисел.

Так что я не уверен, происходит ли время из-за сборщика мусора или, возможно, интерпретатора, выполняющего каждый шаг цикла for (странно, если первое выполнение все еще короткое). Я подумал, может быть, для всех других массивов, установив для них нестатические слабые ссылки, чтобы сборщик мусора мог их очистить, но, похоже, все, что я пытаюсь, это с одинаковыми временными эффектами. Таким образом, вопрос в том, что при использовании больших массивов объектов, какой самый эффективный способ выделить пространство для них. На данный момент они статичны, но не являются окончательными, поскольку размер часто меняется из-за предпочтений пользователя. Любая помощь будет большой благодарностью.

  • Обратите внимание, что это просто пример кода, calcSpec () вызывается каждый раз, когда пользователь изменяет параметры или загружается новый аудиофайл для вычисления частотного спектра данных, тогда только после вызова calcSpec пользователь может вызывать fillArrays () , Что касается профилирования, я использую MemoryAnalyzer и трекер распределения. Странно, что увеличение времени происходит только в fillArrays (). Первое выполнение занимает 4 секунды, второе (без повторного вызова calcSpec (), поэтому снова используются те же данные спектра) - 30 секунд. Как в Mat, так и в трекере выделения, оставшийся размер и размер выделения одинаковы для каждого выполнения.
...