Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PhantomJS huge memory consumption after taking screenshot

I am using PhantomJS via Selenium and encountered a problem on one website with a lot of images.

When I am trying to take screenshot PhantomJS process memory consumption gets very high, ≈400-450 MB (≈100 MB before screenshot)

With --load-images=no it is better, ≈70-100 MB.

Is there any way to solve this issue without disabling images completely? Maybe it is possible to take screenshot of visible area only instead of full page?

With other WebDrivers (such as Chrome) it is working fine.

class Program
{
    public static RemoteWebDriver CreatePhantomJsDriver()
    {
        var service = PhantomJSDriverService.CreateDefaultService();
        //service.AddArgument("--load-images=no");

        var options = new PhantomJSOptions();
        options.AddAdditionalCapability("phantomjs.page.settings.userAgent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36");

        return new PhantomJSDriver(service, options);
    }

    public static void SaveScreenshot(RemoteWebDriver driver)
    {
        try
        {
            driver.TakeScreenshot().SaveAsFile(DateTime.Now.Ticks + ".jpg", ImageFormat.Jpeg);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    static void Main(string[] args)
    {
        using (var driver  = CreatePhantomJsDriver())
        {
            driver.Manage().Window.Size = new Size(1600, 1200);

            driver.Url = "http://color-looks.ru/index";

            Thread.Sleep(5000);

            SaveScreenshot(driver);

            Thread.Sleep(5000);
        }
    }
}

(it is not the website I was using because it requires login/password auth, just some image heavy website from Google, memory consumption is a bit lower but still huge — ≈300 MB)

like image 781
Alex P. Avatar asked Aug 31 '15 07:08

Alex P.


1 Answers

The method TakeScreenshot returns a Bitmap object. The code sample you provided does not dispose of this object, so the GDI object is hanging around in memory for a long time (possibly indefinitely).

Change your code to this:

public static void SaveScreenshot(RemoteWebDriver driver)
{
    try
    {
        using(var screenshot = driver.TakeScreenshot())
        {
            screenshot.SaveAsFile(DateTime.Now.Ticks + ".jpg", ImageFormat.Jpeg);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
like image 199
brianfeucht Avatar answered Nov 07 '22 10:11

brianfeucht