Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[🐛 Bug]: Memory not being properly released #14364

Closed
freyfrey01 opened this issue Aug 9, 2024 · 14 comments
Closed

[🐛 Bug]: Memory not being properly released #14364

freyfrey01 opened this issue Aug 9, 2024 · 14 comments

Comments

@freyfrey01
Copy link

freyfrey01 commented Aug 9, 2024

What happened?

I've noticed that selenium chromeDriver (have also tested edgeDriver) 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. Currently using Chrome and chromeDriver v127 and Selenium 4.23.0 (have also tried selenium 4.15.0)

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".

How can we reproduce the issue?

I've tried the following implementations. I then create 15 scheduled tasks using Task Scheduler to run the script every minute for 5 minutes.

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)
        {
            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)
        {
            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.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
            }
        }
    }

Relevant log output

Before running scripts: https://i.sstatic.net/TH8o9XJj.png
10 minutes of no activity before running scripts: https://i.sstatic.net/2YTPurM6.png
Running scripts for 5 minutes: https://i.sstatic.net/wjVFDiIY.png
10 minutes of no activity after running scripts: https://i.sstatic.net/QX6aJsnZ.png

Operating System

Windows 10

Selenium version

C# 4.23.0

What are the browser(s) and version(s) where you see this issue?

Chrome 127

What are the browser driver(s) and version(s) where you see this issue?

ChromeDriver 127.0.6533.99

Are you using Selenium Grid?

No response

Copy link

github-actions bot commented Aug 9, 2024

@freyfrey01, thank you for creating this issue. We will troubleshoot it as soon as we can.


Info for maintainers

Triage this issue by using labels.

If information is missing, add a helpful comment and then I-issue-template label.

If the issue is a question, add the I-question label.

If the issue is valid but there is no time to troubleshoot it, consider adding the help wanted label.

If the issue requires changes or fixes from an external project (e.g., ChromeDriver, GeckoDriver, MSEdgeDriver, W3C), add the applicable G-* label, and it will provide the correct link and auto-close the issue.

After troubleshooting the issue, please add the R-awaiting answer label.

Thank you!

@nvborisenko
Copy link
Member

Interesting!

I have tried on my end and memory consumption stays stable.

@freyfrey01 which piece of code we should consider to reproduce the issue?

@freyfrey01
Copy link
Author

freyfrey01 commented Aug 9, 2024

Hello @nvborisenko, all of the code I provided causes the issue. Create a C# Console App with any of the implementations above (your most preferred for properly cleaning up after driver use). Create 15 scheduled tasks that run the program every minute for 5 minutes. Every minute you should see 15 instances of chromedriver.exe start then go away. After the 5 minutes are completed, observe the memory usage using Microsoft's RamMap software particularly the row with "Usage" column as "Unused" and observe the "Active" column for that row before and after testing. Also recommend testing on a machine that has lots of available RAM that is unused to get proper metrics as running on laptop can give sparse metrics as memory get reallocated when usuage is too high.

All code I provided is for simple reproduction but in our production environment where we use the driver, we perform the logic most similar to this:

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
            ///EXECUTE WHATEVER DRIVER NEEDS TO DO
            
            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
        }
    }
}

@nvborisenko
Copy link
Member

ChromeDriver with default options? Or you use --sandbox argument parameter?

@freyfrey01
Copy link
Author

@nvborisenko default options, on our production machine we provide options such as --no-sandbox, --headless, --incognito, and --start-maximized but for the purposes of my testing for this issue, I've kept it as minimal as possible just using default options, launching chrome, waiting 3 seconds, then quitting chrome.

@nvborisenko
Copy link
Member

Most likely this is your case: https://issues.chromium.org/issues/42323783

@freyfrey01
Copy link
Author

freyfrey01 commented Aug 9, 2024

@nvborisenko can you elaborate? I actually don't see any zombie/orphaned processes within task manager or resource monitor. For my testing which was outlined above with the screenshots and sample code, --no-sandbox was not used so don't see the connection between the issue linked and my example codes?

As mentioned as well, this is also the case with edgeDriver, do not see different results whether I use EdgeDriver or ChromeDriver

@nvborisenko
Copy link
Member

Then it becomes harder...

There is 2 types of resources: managed and unmanaged. I don't believe we don't release managed resources, it is kinda "impossible". Can you monitor what exactly eats your memory?

  • network connection
  • open file descriptor
  • external processes (seleniummanager, chromedriver, chrome)
  • something else?

@freyfrey01
Copy link
Author

freyfrey01 commented Aug 9, 2024

@nvborisenko I am very sure it has something to do with the selenium implementation but unsure where. This memory increase never occurs when the chrome bots are not running.
I've also taken the liberty of running the following code in Visual Studio and using Diagnostic tools to view the memory usage.
I took 3 snapshots of memory as follows:

  1. Before starting the chrome driver.
  2. Directly after starting chrome driver (after the Task.Delay(10000))
  3. After chromeDriver.Quit() (after the second Task.Delay(10000))

I would have expected my heap size and Objects Diff to have decreased after doing chromeDriver.Quit()
image

public class Program
{
    private static async Task Main(string[] args)
    {
        ChromeDriver chromeDriver = new();
        await Task.Delay(10000); //allow chrome to open for some short time
        chromeDriver.Quit(); //quit to fully close browser and release resources
        await Task.Delay(10000); //allow chrome to open for some short time

        Console.ReadKey();
    }
}

This is an inspection of the managed memory comparing the first snapshot (chromedriver not launched yet) and the final snapshot (chromedriver should be terminated):
image

@nvborisenko
Copy link
Member

I tested this code:

for (int i = 0; i < 10; i++)
{
    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
}

And memory consumption looks like:
image

I don't see any mystic.

Then I tried the following:

for (int i = 0; i < 50; i++)
{
    ChromeDriver chromeDriver = new();
    chromeDriver.Quit(); //quit to fully close browser and release resources
}

And the results:
image

I don't see memory leak of .net managed resources.

@freyfrey01
Copy link
Author

@nvborisenko would you be able to provide screenshots of RamMap from Microsoft similar to the ones I provided for before and after running the code you provided?

@nvborisenko
Copy link
Member

nvborisenko commented Aug 11, 2024

Unfortunately no, I don't want to care about how .net manages memory and ,moreover, what RamMap shows to you. What I see that actual OS memory is not eaten by selenium.

UPD: I looked at your screenshots and I don't see criminal. Please come back with reproducible scenario when selenium eats Gigabytes.

@freyfrey01
Copy link
Author

@nvborisenko has there been a proper fix to #13656. This is the root of my problems

Copy link

This issue has been automatically locked since there has not been any recent activity since it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked and limited conversation to collaborators Sep 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants