Фоновая служба / работник не сборщик мусора - PullRequest
0 голосов
/ 24 марта 2019

Мне нужно иметь IHostedService или «Worker Service», но я столкнулся с интересной загадкой, которая заключается в том, что сборщик мусора не запускается в «подходящее» время.Скорее он просто не собирает никаких ресурсов, в результате чего приложение просто увеличивает использование памяти (во время отладки GC вообще не происходит).

Я сделал все мыслимые вещи, включая выполнение всех моих задачвернуть некоторое значение и, используя, где это возможно, операторы использования.Также абстрагирование нескольких слоев с помощью Dependency Injection (чтобы убедиться, что есть несколько мест, которые должны сообщать среде выполнения, что это подходит для запуска сборки мусора.

Мое единственное «решение», которое не является решением,является ручным запуском GC.Collect ();

namespace Worker
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation($"Worker running at: {DateTime.Now}");

                var files = Directory.EnumerateFiles(@"C:\\repos\");

                var date = files.Select(f => File.ReadAllBytesAsync(f));

                GC.Collect();
            }
        }
    }
}

В результате мой код, без ручного запуска GC, будет раздуваться, чтобы максимально использовать доступную память, однако при ручном GC это может выполняться длячасов без заметных изменений в использовании ресурсов


Решение Использование настроек, упомянутых в этой статье: https://dotnet.github.io/orleans/1.5/Documentation/Deployment-and-Operations/Configuration-Guide/Configuring-.NET-Garbage-Collection.html

1 Ответ

1 голос
/ 24 марта 2019

Это ожидаемое поведение сервера GC. Он настроен так, чтобы наилучшим образом использовать доступную память, и поэтому не будет собирать, если в нем действительно нет необходимости. Это действительно проблема? Операционная система способна передавать и выгружать память по мере необходимости, поэтому, если вы работаете в 64-битной среде, это не должно иметь влияния в большинстве сценариев. Если это все еще вызывает беспокойство, есть несколько альтернатив:

  • Самое простое решение - перейти на рабочую станцию ​​GC, которая способ более агрессивна и автоматически собирает память через равные промежутки времени. Установка gcServer Настройка на false активирует рабочую станцию ​​GC
  • Вы можете играть с количеством куч, выделенных GC. Если процессор имеет большое количество ядер, это может оказать заметное влияние. Это можно сделать с помощью настройки GCHeapCount. См. эту статью от Maoni Stephens для получения дополнительной информации
  • Вы можете создать задание Windows , чтобы ограничить объем памяти, доступный для процесса. Однако это намного сложнее, поскольку, насколько мне известно, в Windows нет встроенного инструмента для этого

.NET Core 3.0 принесет новые настройки для настройки GC для сценариев с нехваткой памяти, но он не будет выпущен до второго семестра.

...