Description
Description
When application creates many short-living configuration roots, which use files it results in memory leaks around FileSystemWatcher
class (in our case we setup test environment for each test and it leads to memory/performance issues as we have around 100k tests).
I've checked code and see that while ConfigurationRoot.Dispose
disposes IConfigurationProvider
instances, FileConfigurationProvider.Dispose
disposes only _changeTokenRegistration
and file (folder actually) watch infrastructure in FileConfigurationSource
is never disposed.
Reproduction Steps
internal class Program
{
static void Main()
{
const int iterations = int.MaxValue;
for (var i = 0; i < iterations; i++)
{
Test();
}
}
static void Test()
{
var config = new ConfigurationBuilder().AddXmlFile("settings.xml", false, true).Build();
(config as IDisposable)?.Dispose();
}
}
Expected behavior
No memory leaks
Actual behavior
Memory leaks
We need to support two runtimes currently, so results are for .NET7 and NET48
.NET 7 runtime after ~78k iterations
where byte[] instances are
In NETFX 4.8 situation is even worse (expected, as it doesn't have all improvements to file watcher related code)
Regression?
Nope
Known Workarounds
passing external PhysicalFileProvider
instance and dispose it explicitly fixes leak completely:
using var fileProvider = new PhysicalFileProvider(AppContext.BaseDirectory);
using var config = new ConfigurationBuilder().AddXmlFile(fileProvider, "settings.xml", false, true).Build() as IDisposable;
Configuration
No response
Other information
No response