What's the performance difference of puppeteer.launch() versus puppeteer.connect()?

Viewed 9145

I'm currently using an svg conversion library which wraps puppeteer:
https://github.com/etienne-martin/svg-to-img

After each call to its convert function it waits 500 ms and if there aren't any other calls then it closes the browser instance and on the subsequent call it will again call puppeteer.launch.

I'm using this inside of a docker container running in a Kubernetes cluster. I'm wondering how expensive it is to continually call puppeteer.launch versus connecting to an already running instance of headless chrome.

I'm considering instead just always having a docker container running an instance of headless chrome and connect to it from my docker container doing the svg conversion.

Before doing this though I wanted to get a sense of what is going on behind on the scenes of launch vs connect.

2 Answers

Short Answer:

Using puppeteer.connect() / browser.disconnect() whenever possible is best from a performance standpoint and is ā‰ˆ 146 times faster than using puppeteer.launch() / browser.close() (according to my benchmark tests).

Detailed Answer:

I ran some tests to compare the performance of calling puppeteer.connect() / browser.disconnect() versus puppeteer.launch() / browser.close().

Each method was tested 10,000 times, and the total time for all iterations and the average time for each iteration were recorded.

My tests found that using puppeteer.connect() / browser.disconnect() is approximately 146 times faster than using puppeteer.launch() / browser.close().

You can perform the tests on your own machine using the code provided below.

Benchmark (puppeteer.launch() / browser.close()):

'use strict';

const puppeteer = require('puppeteer');
const { performance } = require('perf_hooks');

const iterations = 10000;

(async () => {
  let browser;
  
  const start_time = performance.now();
  
  for (let i = 0; i < iterations; i++) {
      browser = await puppeteer.launch();
      
      await browser.close();
  }
  
  const end_time = performance.now();
  
  const total_time = end_time - start_time;
  const average_time = total_time / iterations;
  
  process.stdout.write (
      'Total Time:\t' + total_time + ' ms\n'
    + 'Average Time:\t' + average_time + ' ms\n'
    + 'Iterations:\t' + iterations.toLocaleString() + '\n'
  );
})();

Result:

Total Time: 1339075.0866550002 ms

Average Time: 133.90750866550002 ms

Iterations: 10,000


Benchmark (puppeteer.connect() / browser.disconnect()):

'use strict';

const puppeteer = require('puppeteer');
const { performance } = require('perf_hooks');

const iterations = 10000;

(async () => {
  let browser = await puppeteer.launch();
  const browserWSEndpoint = browser.wsEndpoint();
  
  browser.disconnect();
  
  const start_time = performance.now();
  
  for (let i = 0; i < iterations; i++) {
    browser = await puppeteer.connect({
      browserWSEndpoint,
    });
    
    browser.disconnect();
  }
  
  const end_time = performance.now();
  
  const total_time = end_time - start_time;
  const average_time = total_time / iterations;
  
  process.stdout.write (
      'Total Time:\t' + total_time + ' ms\n'
    + 'Average Time:\t' + average_time + ' ms\n'
    + 'Iterations:\t' + iterations.toLocaleString() + '\n'
  );
  
  process.exit();
})();

Result:

Total Time: 9198.328596000094 ms

Average Time: 0.9198328596000094 ms

Iterations: 10,000


Puppeteer Source Code:

You can view what is happening behind the scenes by inspecting the source code of the functions in question:

puppeteer.launch()

puppeteer.launch() starts the chromium instance and connects to it afterwards. The start of a chromium instance takes between 100 and 150ms depending on your hardware. The connect happens instantly (as it is a websocket on a local machine).

puppeteer.connect()

puppeteer.connect() only connects to an existing chromium instance.

  • If the instance you are connecting to is one the same machine as your script, this should happen instantly as before (<1ms).
  • If you run the chromium instance on a second machine, you will introduce a network delay for the puppeteer.connect() call and all following puppeteer function calls. The delay will depend entirely on the network, but if your machines are in the same location this should be below 10ms.

svg-to-img

Regarding the library you linked: It looks like the library you linked does not support connecting to a puppeteer instance. You could also put the library on a machine and offer an API that receives the SVG code and returns the image. That way you could keep the chromium instances running.

Related