I've been struggling trying to identify why one of my services memory footprint grows over time. In trying to identify the memory leak, I setup a test environment and commented out code, one call at a time to try to isolate the culprit. To my surprise, what I was left with a simple program that opened a connection to an Sql Server database, and closed it without sending any commands, yet still had the memory leak. The entire .NET 4.8 program is below.
static void Main(string[] args)
{
var Logger = new LoggerConfiguration()
.WriteTo.File(LogFilePath, rollingInterval: RollingInterval.Day)
.CreateLogger();
while (true)
{
PollDB();
Logger.Information($"Memory in use after processing: {Process.GetCurrentProcess().PrivateMemorySize64.ToString("N0")}B");
Thread.Sleep(new TimeSpan(4, 0, 0));
}
}
static private void PollDB()
{
string cstring = ConfigurationManager.ConnectionStrings["AdminDB"].ConnectionString;
using (var conn = new SqlConnection(cstring))
{
conn.Open();
conn.Close();
}
}
Here is the log output:
2022-01-25 14:12:10.641 -05:00 [INF] Memory in use after processing: 15,056,896B
2022-01-25 18:12:10.796 -05:00 [INF] Memory in use after processing: 24,465,408B
2022-01-25 22:12:11.230 -05:00 [INF] Memory in use after processing: 32,997,376B
2022-01-26 02:12:11.384 -05:00 [INF] Memory in use after processing: 41,586,688B
2022-01-26 06:12:11.824 -05:00 [INF] Memory in use after processing: 49,975,296B
2022-01-26 10:12:11.947 -05:00 [INF] Memory in use after processing: 58,253,312B
2022-01-26 14:12:12.420 -05:00 [INF] Memory in use after processing: 66,899,968B
2022-01-26 18:12:12.543 -05:00 [INF] Memory in use after processing: 75,354,112B
2022-01-26 22:12:12.773 -05:00 [INF] Memory in use after processing: 83,755,008B
2022-01-27 02:12:13.162 -05:00 [INF] Memory in use after processing: 92,155,904B
2022-01-27 06:12:13.274 -05:00 [INF] Memory in use after processing: 100,581,376B
2022-01-27 10:12:13.716 -05:00 [INF] Memory in use after processing: 109,121,536B
Aside from the serilog code, the only code that could be grabbing memory is the sqlconnection. And I'm pretty sure the serilog code isn't at fault because if I comment out the PollDB() call, there is no memory leak.
Another thing of note. I can take the same program and change the time between database polls to 12 hours and the memory usage will grow at the same rate. In other words, the memory usage is dependent on the length of time the program is running, not the number of sql connections made.
I've used a memory profiler and it's unmanaged memory that is what is growing over time.
Has anyone experienced this before? Is there a connection string parameter that may resolve this issue? An OS hotfix?
Santiago Trujillo