Search code examples
c#selenium-webdriverselenium-chromedriver.net-8.0

C# Selenium ChromeDriver Leaking memory


I'm seeking assistance as I've noticed that selenium chromeDriver in c# has not properly been releasing memory. I've been using RamMap to track memory usage. When not running the following scripts, memory usage does not steadily increase.

Running the scripts below within task scheduler causes memory within the "Unused-Active" entry of RamMap to increase on every run. I've confirmed there are no active chromedriver or chrome processes within resource monitor, task manager, or RamMap. Selenium.WebDriver v4.23.0. Chrome and ChromeDriver v127.

Screenshots of RamMap for reference, as seen the "Unused-Active" entry rises significantly after about 5 minutes of running the scripts. This value does not rise when the scripts are not running.

Root of concern as shown in the screenshots is "Unused - Active" goes from 7000KB to 50000KB in the span of 5 minutes. Over the course of 24 hours, if that continues, that's an increase of nearly 12384000KB or about 12 GB. This is causing a major performance problem as after a week of running, the machine gets over 80% usage of RAM that's just unused but still considered "Active".

Before running scripts (After reboot) - Value does not increase: Before running scripts

10 minutes of downtime - no scripts running 10 minutes of downtime

15 scheduled tasks launching the console app every minute for 5 minutes - Value increased significantly 15 scheduled tasks for 5 minutes on 1 minute intervals

10 minutes of downtime - stop the scripts from running 10 minutes of downtime

Reproducible code I've tried: (Create C# console app and configure the project to run via 15 scheduled tasks in Task Scheduler every minute.)

using OpenQA.Selenium.Chrome;
namespace ChromeBotTest
{
    public class Program
    {
        private static async Task Main(string[] args)
        {
            using (ChromeDriver? chromeDriver = new()) //using statement for automatic disposal
            {
                await Task.Delay(3000); //allow chrome to open for some short time
                chromeDriver.Close(); //close all windows
                chromeDriver.Quit(); //quit to fully close browser and release resources
            }
        }
    }
}
using OpenQA.Selenium.Chrome;
namespace ChromeBotTest
{
    public class Program
    {
        private static async Task Main(string[] args)
        {
            using (ChromeDriver? chromeDriver = new()) //using statement for automatic disposal
            {
                await Task.Delay(3000); //allow chrome to open for some short time
                chromeDriver.Quit(); //quit to fully close browser and release resources
            }
        }
    }
}
using OpenQA.Selenium.Chrome;
namespace ChromeBotTest
{
    public class Program
    {
        private static async Task Main(string[] args)
        {
            ChromeDriver chromeDriver = new(); 
            await Task.Delay(3000); //allow chrome to open for some short time
            chromeDriver.Quit(); //quit to fully close browser and release resources
        }
    }
}
using OpenQA.Selenium.Chrome;
namespace ChromeBotTest
{
    public class Program
    {
        private static async Task Main(string[] args)
        {
            ChromeDriver? chromeDriver = new();
            await Task.Delay(3000); //allow chrome to open for some short time
            chromeDriver.Close(); //close all windows
            chromeDriver.Quit(); //quit to fully close browser and release resources
            chromeDriver?.Dispose(); //dispose incase chromeDriver is not properly disposed
            chromeDriver = null; //set to null to ensure its cleared
        }
    }
}
    using OpenQA.Selenium.Chrome;
    namespace ChromeBotTest
    {
        public class Program
        {
            private static async Task Main(string[] args)
            {
                ChromeDriver? chromeDriver = new();
                await Task.Delay(3000); //allow chrome to open for some short time
                chromeDriver.Close(); //close all windows
                chromeDriver.Quit(); //quit to fully close browser and release resources
                chromeDriver?.Dispose(); //dispose incase chromeDriver is not properly disposed
                chromeDriver = null; //set to null to ensure its cleared
                await Task.Delay(2000); //allow 2 second delay
                GC.Collect();
                GC.WaitForPendingFinalizers(); //clean up garabage collection
                GC.Collect();
                await Task.Delay(10000); //wait 10 seconds to allow garbage collection sufficent time to execute
            }
        }
    }

Solution

  • Tracked it down to Trellix/Mcafee holding zombied handles to the terminated processes using RamMap and https://github.com/randomascii/blogstuff/tree/main/FindZombieHandles