Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 446
Dana Asbury Avatar asked Dec 01 '22 10:12

Dana Asbury


1 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.connect() source code
  • browser.disconnect() source code
  • puppeteer.launch() source code
  • browser.close() source code
like image 52
Grant Miller Avatar answered Jan 28 '23 16:01

Grant Miller