Что-то блокирует мою память, и программа зависает на GC.Collect () или GC.GetTotalAmountOfMemory (true) - PullRequest
4 голосов
/ 14 марта 2012

всякий раз, когда я вызываю GC.Collect() или GC.GetTotalAmountOfMemory(true), вся программа просто зависает.Теперь я знаю, что вы скажете: не звоните GC.Collect(), GC позаботится о себе.Проблема в том, что в моем случае это не так, что-то зависает в памяти, и сборщик мусора не может от этого избавиться.

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

* редактировать то, что я полностью забыл: Иногда, когда я вызываю один из двух методов GC, использование памяти увеличивается на ~ 10 килобайт / секунду

* edit2 Я должен исправить себя: GC.Collect () работает просто отлично.Только GC.GetTotalMemory (true) зависает.GC.GetTotalMemory (false) тоже отлично работает.

* edit3 и yup, как уже говорили некоторые из вас: похоже, где-то есть финализатор.Когда я запускаю WaitForPendingFinalizers (), он просто сидит и ничего не делает.

хорошо, теперь я совершенно сбит с толку: когда я ввожу GC.GetTotalMemor(true) или GC.WaitForPendingFinalizers() в непосредственное окно Visual Studio после приостановки отладчика, программа зависает (это то, что я делал все время ... Я чувствую себя глупо сейчас ).Когда я добавляю его к своему обычному исходному коду и компилирую, он работает просто отлично.

Извините за весь пух, похоже, у утечки памяти есть другая причина.

Ответы [ 2 ]

7 голосов
/ 14 марта 2012

Вы отменяете какие-либо финализаторы? Когда финализатор не возвращается (возможно, вы ожидаете в любой момент другого потока), приложение может зависнуть. GC.Collect() вызывает финализатор, но он никогда не возвращается, поскольку ожидает возврата финализатора. Это также может быть причиной утечки памяти, поскольку сборщик мусора не может завершить сборку мусора.

Решение

Вы должны быть в состоянии отладить его, когда сборщик мусора собирает и нажимает «пауза», он должен показать вам трассировку стека, где он висит. Если все идет не так, как надо, возможно, вам нужно проверить разборку, на которой висит ваше приложение.

GetTotalMemory (правда)

Этот метод вызывает сборку мусора, поэтому он такой же, как GC.Collect().

Обновление

Давайте посмотрим на GetTotalMemory:

public static long GetTotalMemory(bool forceFullCollection)
{
    long totalMemory = GC.GetTotalMemory();
    if (!forceFullCollection)
    {
        return totalMemory;
    }
    int remainingSteps = 20;
    long lastMemory = totalMemory;
    float num4;
    do
    {
        GC.WaitForPendingFinalizers();
        GC.Collect();
        totalMemory = lastMemory;
        lastMemory = GC.GetTotalMemory();
        num4 = (float)(lastMemory - totalMemory) / (float)totalMemory;
    }
    while (remainingSteps-- > 0 && (-0.05 >= (double)num4 || (double)num4 >= 0.05));

    return lastMemory;
}

Как видите, GetTotalMemory ожидает финализаторов, поэтому это должен быть финализатор, который вешает приложение. GC.Collect() вызывается, когда финализаторы заканчиваются, и никогда не будет вызван, потому что он никогда не проходит строку раньше.

В любой точке вашего приложения (небезопасный код? Другой поток?) Есть что-то, что выделяет много памяти, в то время как GC никогда не имеет возможности очистить существующую память.

Отказ от ответственности

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

2 голосов
/ 14 марта 2012

Рассматривали ли вы использовать настройки GC режима сервера, чтобы один поток GC работал на ядро ​​процессора?
Вы исследовали проблему, используя счетчики производительности, дампы или профилировщики? Профилировщик памяти ANTS очень полезен, если само приложение не слишком сильно замедляется при его использовании.
Я бы также посмотрел на ваше приложение с помощью Windows Process Explorer, чтобы почувствовать вкус происходящего на стороне памяти.

...