Утечки памяти при использовании массива double - PullRequest
5 голосов
/ 06 мая 2010

У меня есть часть кода, которая работает с большими массивами double (содержит минимум 6000 элементов) и выполняется несколько сотен раз (обычно 800).

Когда я использую стандартный цикл, вот так:

double[] singleRow = new double[6000];
int maxI = 800;
for(int i=0; i<maxI; i++)
{
singleRow = someObject.producesOutput();
//...
// do something with singleRow
// ...
}

Использование памяти увеличивается примерно на 40 МБ (с 40 МБ в начале цикла до 80 МБ в конце).

Когда я заставляю использовать сборщик мусора для выполнения на каждой итерации, использование памяти остается на уровне 40 МБ (увеличение незначительно).

double[] singleRow = new double[6000];
int maxI = 800;
for(int i=0; i<maxI; i++)
{
singleRow = someObject.producesOutput();
//...
// do something with singleRow
// ...
GC.Collect()
}

Но время выполнения в 3 раза больше! (это важно)

Как заставить C # использовать одну и ту же область памяти вместо выделения новых? Примечание. У меня есть доступ к коду класса someObject, поэтому, если он понадобится, я могу его изменить.

Ответы [ 3 ]

7 голосов
/ 07 мая 2010

Почему вы выделяете большой, пустой singleRow только для его перезаписи? Возможно, вам следует передать массив, чтобы его значения были изменены на месте. Это позволит вам использовать его повторно.

double[] singleRow = new double[6000];
int maxI = 800;
for(int i=0; i<maxI; i++)
{
    someObject.FillWithOutput(singleRow);
    //...
    // do something with singleRow
    // ...
}

Если метод иногда заполняет менее 6000 элементов, он может просто вернуть счетчик заполнения. Кроме того, вы можете использовать List<double>, что позволит изменить размер.

3 голосов
/ 07 мая 2010

Создайте singleRow параметр и передайте его вызову producesOutput каждый раз ...

По сути, ваш producesOutput метод, вероятно, каждый раз выделяет новый массив, а переназначение singleRow просто помечает старую память как доступно для удаления, но не запускает GC по соображениям производительности.

0 голосов
/ 07 мая 2010

Тебе это не понравится, но если ты заставляешь GC, ты делаешь что-то не так. Имейте в виду, что память может расти до тех пор, пока не возникнет необходимость активировать GC - это ХОРОШО, потому что это означает, что GC не запускается, пока не потребуется.

Вот глупо звучащий тест, но он может пролить некоторый свет на происходящее. Внутри FillWithOutput () закомментируйте большую часть его функциональности. Затем запустите свой цикл и измерьте память. Постепенно не комментируйте кусочки, пока не увидите сообщение. Теперь вы приближаетесь к тому, что вызывает «утечку».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...