Утечки памяти при использовании массива дважды

У меня есть часть кода, который воздействует на большие массивы double (содержащий приблизительно 6 000 элементов, по крайней мере), и выполняется несколько сотен раз (обычно 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 МБ в beggining цикла к 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 класс, поэтому если это было бы необходимо, я могу изменить его.

5
задан Gacek 6 May 2010 в 19:57
поделиться

3 ответа

Почему вы выделяете большой пустой 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 , что позволит изменять размер.

7
ответ дан 13 December 2019 в 22:03
поделиться

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

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

0
ответ дан 13 December 2019 в 22:03
поделиться

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

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

3
ответ дан 13 December 2019 в 22:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: