G C .Collect () не работает при запуске один раз в день и при непрерывном запуске - PullRequest
1 голос
/ 17 марта 2020

У меня есть Windows Сервис. Есть 2 проекта; проект службы (C#), в котором размещается класс службы, содержащий весь код на основе таймера (OnStart, OnStop, Timer_Elapsed et c.) и файлы конфигурации. У другого проекта (VB) есть код того, что служба фактически делает в классе Manager.

Эта служба windows имеет утечки памяти, и скорость увеличения использования памяти составляет ~ 50 МБ / день. Через месяц его использование памяти достигает почти 1,5 ГБ.

В долгосрочной перспективе моя компания планирует внедрить IDisposable, но в качестве временного решения мы решили использовать G C .Collect (). Поэтому я добавил G C .Collect () в timer_elapsed (), который вызывается каждые 3 секунды, начиная с poll_interval = 3. Я также установил некоторые объекты, которые не реализуют IDisposable, в null / Nothing.

int counter = 0;

private void Timer_Elapsed()
{
    // create instance of Manager.cs
    try
    {
        // do something
    }
    catch (Exception ex)
    {
        // handle errors
    }
    finally
    {
        Process currentProcess = Process.GetCurrentProcess();
        Logger logger = LogManager.GetCurrentClassLogger();
        logger.Debug("Working Set " + currentProcess.WorkingSet64);

        counter += 1;
        if (counter == counterThreshold)
        {
            counter = 0;
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
            GC.WaitForPendingFinalizers();
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
            logger.Debug("GC");
            logger.Debug("Gen 0: " + GC.CollectionCount(0));
            logger.Debug("Gen 1: " + GC.CollectionCount(1));
            logger.Debug("Gen 2: " + GC.CollectionCount(2));
        }

        currentProcess.Dispose();
        logger = null;

        // set objects to null

        _timer.Start();
    }
}

Когда counterThreshold установлен в 1, использование памяти всегда остается ~ 28 МБ. Когда он установлен на 10, использование остается ~ 28 МБ +/- 0,5 МБ. Когда он установлен на 75 (потому что когда poll_interval = 3, timer_elapsed вызывается 20 раз / мин, поэтому установка counterThreshold на 75 означает вызов G C .Collect () каждые 3,75 минуты), я вижу, что G C .Collect (), кажется, не имеет большого значения.

12:53:24|SVC.Service1|Working Set 27172864
12:53:27|SVC.Service1|Working Set 27762688
12:53:30|SVC.Service1|Working Set 27844608
12:53:33|SVC.Service1|Working Set 27926528
12:53:36|SVC.Service1|Working Set 28012544
12:53:39|SVC.Service1|Working Set 28094464
12:53:42|SVC.Service1|Working Set 28176384
12:53:45|SVC.Service1|Working Set 28258304
12:53:48|SVC.Service1|Working Set 28344320
12:53:52|SVC.Service1|Working Set 28426240
12:53:55|SVC.Service1|Working Set 28516352
12:53:58|SVC.Service1|Working Set 28598272
12:54:01|SVC.Service1|Working Set 28676096
12:54:04|SVC.Service1|Working Set 28762112
12:54:07|SVC.Service1|Working Set 28839936
12:54:10|SVC.Service1|Working Set 28921856
12:54:13|SVC.Service1|Working Set 29003776
12:54:16|SVC.Service1|Working Set 29089792
12:54:19|SVC.Service1|Working Set 29179904
12:54:22|SVC.Service1|Working Set 29257728
12:54:25|SVC.Service1|Working Set 29343744
12:54:28|SVC.Service1|Working Set 29425664
12:54:31|SVC.Service1|Working Set 29503488
12:54:34|SVC.Service1|Working Set 29536256
12:54:37|SVC.Service1|Working Set 29618176
12:54:40|SVC.Service1|Working Set 29696000
12:54:43|SVC.Service1|Working Set 29777920
12:54:46|SVC.Service1|Working Set 29859840
12:54:49|SVC.Service1|Working Set 29945856
12:54:52|SVC.Service1|Working Set 30081024
12:54:55|SVC.Service1|Working Set 30162944
12:54:58|SVC.Service1|Working Set 30248960
12:55:01|SVC.Service1|Working Set 30330880
12:55:04|SVC.Service1|Working Set 30416896
12:55:07|SVC.Service1|Working Set 30511104
12:55:10|SVC.Service1|Working Set 30597120
12:55:13|SVC.Service1|Working Set 30674944
12:55:16|SVC.Service1|Working Set 30756864
12:55:19|SVC.Service1|Working Set 30842880
12:55:22|SVC.Service1|Working Set 30924800
12:55:25|SVC.Service1|Working Set 31002624
12:55:28|SVC.Service1|Working Set 31064064
12:55:31|SVC.Service1|Working Set 31158272
12:55:34|SVC.Service1|Working Set 31240192
12:55:37|SVC.Service1|Working Set 31318016
12:55:40|SVC.Service1|Working Set 31395840
12:55:43|SVC.Service1|Working Set 31547392
12:55:46|SVC.Service1|Working Set 31543296
12:55:49|SVC.Service1|Working Set 31543296
12:55:53|SVC.Service1|Working Set 31547392
12:55:56|SVC.Service1|Working Set 31543296
12:55:59|SVC.Service1|Working Set 31490048
12:56:02|SVC.Service1|Working Set 31494144
12:56:05|SVC.Service1|Working Set 31490048
12:56:08|SVC.Service1|Working Set 31494144
12:56:11|SVC.Service1|Working Set 31494144
12:56:14|SVC.Service1|Working Set 31494144
12:56:17|SVC.Service1|Working Set 31490048
12:56:20|SVC.Service1|Working Set 31494144
12:56:23|SVC.Service1|Working Set 31543296
12:56:26|SVC.Service1|Working Set 31547392
12:56:29|SVC.Service1|Working Set 31547392
12:56:32|SVC.Service1|Working Set 31547392
12:56:35|SVC.Service1|Working Set 31551488
12:56:38|SVC.Service1|Working Set 31543296
12:56:41|SVC.Service1|Working Set 31543296
12:56:44|SVC.Service1|Working Set 31543296
12:56:47|SVC.Service1|Working Set 31547392
12:56:50|SVC.Service1|Working Set 31543296
12:56:53|SVC.Service1|Working Set 31543296
12:56:56|SVC.Service1|Working Set 31547392
12:56:59|SVC.Service1|Working Set 31547392
12:57:02|SVC.Service1|Working Set 31547392
12:57:05|SVC.Service1|Working Set 31547392
12:57:08|SVC.Service1|Working Set 31547392
12:57:08|SVC.Service1|GC
12:57:08|SVC.Service1|Gen 0: 3
12:57:08|SVC.Service1|Gen 1: 2
12:57:08|SVC.Service1|Gen 2: 2
12:57:11|SVC.Service1|Working Set 31956992
12:57:14|SVC.Service1|Working Set 31956992
12:57:17|SVC.Service1|Working Set 31956992
12:57:20|SVC.Service1|Working Set 31952896
12:57:23|SVC.Service1|Working Set 31952896
12:57:26|SVC.Service1|Working Set 31956992
12:57:29|SVC.Service1|Working Set 31899648
12:57:32|SVC.Service1|Working Set 31903744
12:57:35|SVC.Service1|Working Set 31899648
12:57:38|SVC.Service1|Working Set 31903744
12:57:41|SVC.Service1|Working Set 31903744
12:57:44|SVC.Service1|Working Set 31903744
12:57:47|SVC.Service1|Working Set 31903744
12:57:50|SVC.Service1|Working Set 31903744
12:57:53|SVC.Service1|Working Set 31899648
12:57:56|SVC.Service1|Working Set 31903744
12:57:59|SVC.Service1|Working Set 31899648
12:58:02|SVC.Service1|Working Set 31903744
12:58:05|SVC.Service1|Working Set 31903744
12:58:08|SVC.Service1|Working Set 31903744
12:58:11|SVC.Service1|Working Set 31903744
12:58:14|SVC.Service1|Working Set 31903744
12:58:17|SVC.Service1|Working Set 31899648
12:58:20|SVC.Service1|Working Set 31899648
12:58:23|SVC.Service1|Working Set 31903744
12:58:26|SVC.Service1|Working Set 31903744
12:58:29|SVC.Service1|Working Set 31903744
12:58:32|SVC.Service1|Working Set 31899648
12:58:35|SVC.Service1|Working Set 31899648
12:58:38|SVC.Service1|Working Set 31903744
12:58:42|SVC.Service1|Working Set 31903744
12:58:45|SVC.Service1|Working Set 31899648
12:58:48|SVC.Service1|Working Set 31903744
12:58:51|SVC.Service1|Working Set 31899648
12:58:54|SVC.Service1|Working Set 31903744
12:58:57|SVC.Service1|Working Set 31899648
12:59:00|SVC.Service1|Working Set 31903744
12:59:03|SVC.Service1|Working Set 31903744
12:59:06|SVC.Service1|Working Set 31903744
12:59:09|SVC.Service1|Working Set 31899648
12:59:12|SVC.Service1|Working Set 31903744
12:59:15|SVC.Service1|Working Set 31899648
12:59:18|SVC.Service1|Working Set 31907840
12:59:21|SVC.Service1|Working Set 31899648
12:59:24|SVC.Service1|Working Set 31899648
12:59:27|SVC.Service1|Working Set 32026624
12:59:30|SVC.Service1|Working Set 32030720
12:59:33|SVC.Service1|Working Set 32026624
12:59:36|SVC.Service1|Working Set 32030720
12:59:39|SVC.Service1|Working Set 32030720
12:59:42|SVC.Service1|Working Set 32030720
12:59:45|SVC.Service1|Working Set 32071680
12:59:48|SVC.Service1|Working Set 32067584
12:59:51|SVC.Service1|Working Set 32104448
12:59:54|SVC.Service1|Working Set 32108544
12:59:57|SVC.Service1|Working Set 32108544
13:00:00|SVC.Service1|Working Set 32112640
13:00:03|SVC.Service1|Working Set 32124928
13:00:06|SVC.Service1|Working Set 32202752
13:00:09|SVC.Service1|Working Set 32280576
13:00:12|SVC.Service1|Working Set 32362496
13:00:15|SVC.Service1|Working Set 32473088
13:00:18|SVC.Service1|Working Set 32559104
13:00:21|SVC.Service1|Working Set 32641024
13:00:24|SVC.Service1|Working Set 32722944
13:00:27|SVC.Service1|Working Set 32747520
13:00:30|SVC.Service1|Working Set 32747520
13:00:33|SVC.Service1|Working Set 32690176
13:00:36|SVC.Service1|Working Set 32632832
13:00:39|SVC.Service1|Working Set 32636928
13:00:42|SVC.Service1|Working Set 32628736
13:00:45|SVC.Service1|Working Set 32665600
13:00:48|SVC.Service1|Working Set 32669696
13:00:51|SVC.Service1|Working Set 32669696
13:00:54|SVC.Service1|Working Set 32669696
13:00:54|SVC.Service1|GC
13:00:54|SVC.Service1|Gen 0: 6
13:00:54|SVC.Service1|Gen 1: 4
13:00:54|SVC.Service1|Gen 2: 4
13:00:57|SVC.Service1|Working Set 32673792
13:01:00|SVC.Service1|Working Set 32677888
13:01:03|SVC.Service1|Working Set 32673792
13:01:06|SVC.Service1|Working Set 32677888
13:01:09|SVC.Service1|Working Set 32677888
13:01:12|SVC.Service1|Working Set 32673792
13:01:15|SVC.Service1|Working Set 32677888
13:01:18|SVC.Service1|Working Set 32677888
13:01:21|SVC.Service1|Working Set 32673792
13:01:24|SVC.Service1|Working Set 32673792
13:01:27|SVC.Service1|Working Set 32673792
13:01:30|SVC.Service1|Working Set 32673792
13:01:33|SVC.Service1|Working Set 32628736
13:01:36|SVC.Service1|Working Set 32632832
13:01:39|SVC.Service1|Working Set 32624640
13:01:42|SVC.Service1|Working Set 32628736
13:01:45|SVC.Service1|Working Set 32628736
13:01:48|SVC.Service1|Working Set 32628736
13:01:52|SVC.Service1|Working Set 32628736
13:01:55|SVC.Service1|Working Set 32628736

И когда counterThreshold установлен на 28800 (т. Е. Вызывать G C .Collect () один раз в день), увеличение использования памяти по-прежнему составляет ~ 50 МБ / день, а вызов G C .Collect. (), кажется, не имеет никакого значения.

график использования памяти

Каждый раз, когда я вызываю G C .Collect (), я ожидаю, что использование памяти уменьшите до ~ 28 МБ независимо от того, звоню ли я постоянно или один раз в день.

  1. Что происходит с G C .Collect () при увеличении counterThreshold / когда counterThreshold = 28800?
  2. Почему он работает при непрерывной работе, а не при однократной работе день?
  3. Что я могу сделать с G C, чтобы использование памяти уменьшалось до ~ 28 МБ при каждом вызове G C .Collect () независимо от значения counterThreshold?

1 Ответ

1 голос
/ 17 марта 2020

Скопировано из моего комментария под вопросом:

G C .Collect не решает проблемы утечки памяти. Он не уничтожает объекты, которые живы / на которые ссылаются другие. G C .Collect собирает только объекты в заданных поколениях. Если вы считаете, что у вас есть несколько объектов, которые можно немедленно собрать, например, большое растровое изображение, которое было закрыто, вызов G C .Collect поможет. В противном случае, G C .Collect не сделает много.

Более того, факт, что сборка мусора постоянно выполняется в фоновом режиме. Вызов GC.Collect только заставляет сборщик мусора запускаться сейчас . Если нечего собирать, использование памяти не уменьшится.

Один раз в день не работает или работает непрерывно, работы могут совпадать, что к тому времени, когда GC.Collect вызывается один раз в день, нечего собирать, по сравнению с непрерывным бегом увеличивает вероятность того, что что-то соберет.

...