I need to have an IHostedService, or "Worker Service", but I've come across an interesting conundrum, and that is that the Garbage Collector don't run at the "appropriate" times. Rather it just don't collect any resources, resulting in the application just increasing in memory use, (during debug, there's no GC happening at all).
I have done every thinkable thing, including having all my tasks return some value, and using using-statements where possible. Also abstracting a few layers with Dependency Injection, (to make sure there is multiple places that should communicate to the runtime that it's appropriate to run garbage collection.
My only "solution", which isn't a solution, is to manually run 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();
}
}
}
}
The result is that my code, without manually triggering GC, will bloat to max out the available memory, however, with the manual GC this can run for hours without noticeable changes in resources usage
Solution Using the settings mention in this article: https://dotnet.github.io/orleans/1.5/Documentation/Deployment-and-Operations/Configuration-Guide/Configuring-.NET-Garbage-Collection.html (deprecated)
Updated link: https://learn.microsoft.com/en-us/dotnet/core/run-time-config/garbage-collector
This is an expected behavior of server GC. It is tuned to make the best use of the available memory, and therefore won't collect unless it is really needed. Is that really issue? The OS is capable of paging memory in and out as needed, so if you're running in 64 bits it shouldn't have an impact in most scenarios. If that's still a concern, there are a few alternatives:
gcServer
setting to false
will activates workstation GCGCHeapCount
setting. See this article from Maoni Stephens for more information .NET Core 3.0 will bring new settings to tweak the GC for low-memory scenarios, but it won't be released before the second semester.