microsoft / playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
https://playwright.dev
Apache License 2.0
64.25k stars 3.49k forks source link

[BUG] Memory leak in Chrome on repeated browser open/close #21079

Open rustyhectors opened 1 year ago

rustyhectors commented 1 year ago

Context:

Code Snippet

Help us help you! Put down a short code snippet that illustrates your bug and that we can run and debug locally. For example:

package repro;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import java.util.Map;

public class Repro {
  // Before running, launch chrome with "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9223 --headless
  public static void main(String[] args) throws InterruptedException {
    Playwright playwright = Playwright.create(
      new Playwright.CreateOptions().setEnv(Map.of("PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD", "true")));

    // open one browser/page
    Browser browser = playwright.chromium().connectOverCDP("http://" + "localhost" + ":" + 9223);
    BrowserContext context = browser.newContext();
    Page page = context.newPage();
    page.navigate("https://www.google.com");

    // open/close a browser repeatedly
    while (true) {
      try {
        Browser shortLivedBrowser = playwright.chromium().connectOverCDP("http://" + "localhost" + ":" + 9223);
        shortLivedBrowser.close();
        System.out.println("Opened and closed.");
      } catch (Exception e) {
        System.out.println("Failed to open or close browser.");
        System.out.println(e);
      }
      Thread.sleep(10);
    }
  }
}

Describe the bug Chrome memory usage grows in the "renderer" process.

Baseline before running the repro: Screen Shot 2023-02-21 at 6 50 06 PM

Right after starting: Screen Shot 2023-02-21 at 6 50 19 PM

A minute or two: Screen Shot 2023-02-21 at 6 52 14 PM

About four minutes after starting: Screen Shot 2023-02-21 at 6 54 37 PM

mxschmitt commented 1 year ago

I can confirm that with the following:

// test.mjs
import puppeteer from 'puppeteer';

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/Users/maxschmitt/Library/Caches/ms-playwright/chromium-1048/chrome-mac/Chromium.app/Contents/MacOS/Chromium',
  });
  while (true) {
    console.log("connecting")
    const browser2 = await puppeteer.connect({
      browserWSEndpoint: browser.wsEndpoint(),
    });
    browser2.disconnect();
  }
})().catch(e => {
  console.error(e);
  process.exit(1);
});

the memory also grows linearly. But it grows very slowly for me, after 80k connections the Renderer reached 1GB.

rustyhectors commented 1 year ago

For comparison it took about 2100 iterations with code I provided to get to 1GB memory in the Renderer. I also ran your puppeteer code and confirmed I saw about the same number of iterations to get to 1GB (~80k).

yury-s commented 1 year ago

@rustyhectors it's an upstream issue, can you file it there (https://crbug.com) ?

rustyhectors commented 1 year ago

Filed an issue here https://bugs.chromium.org/p/chromium/issues/detail?id=1418465.

SmartALB commented 3 months ago

We are conducting a sort of mix between a continuous and a load test. Since other tools, such as Artillery, can't represent our scenario, I'm repurposing Playwright for this somewhat. Multiple browsers are opened in tabs, and in an endless loop, a few actions are carried out in all tabs in succession. In any case, I observe with Chromium also a slight linear increase: Starting at about 2.5 GB RAM, the utilization has increased to about 7GB after a good 3 hours. With Firefox, it starts at about 5 GB, and after a significantly shorter period of time, it has reached 8GB. Very noticeable is the behavior with Safari. Here is the utilization shortly after the test began:

safari

BryceBarbara commented 3 months ago

@yury-s the bug ticket filed with chrome was closed as wont-fix. What should we do with this issue?