I've written a small crawler with the help of Puppeteer.
Now I'm facing the challenge that my tests are rather slowly (> 3 seconds for each test). I've been able to track it down to the launch
function of Puppeteer and the usage of Istanbul/nyc.
mocha
, the tests are finished under 400 ms. nyc
, the duration of the tests exceeds 3000 msAll that I'm using is
'use strict';
const puppeteer = require('puppeteer');
module.exports = async function startBrowser() {
const options = {
args: [
// '--no-sandbox',
// '--disable-setuid-sandbox',
// '--disable-dev-shm-usage',
// '--disable-accelerated-2d-canvas',
// '--disable-gpu'
],
headless: false // true
};
return await puppeteer.launch(options);
};
Here is the test I'm using:
'use strict';
/* global describe: false, before: false, it: false,
beforeEach: false, afterEach: false, after: false, window: false, document: false */
const assert = require('assert').strict;
const startBrowser = require('../');
const util = require('util');
describe('Puppeteer', function() {
let pageManager;
it('start the browser', async function() {
this.timeout(10000);
console.time('startBrowser');
const browser = await startBrowser();
console.timeEnd('startBrowser');
assert(browser);
console.time('closeBrowser');
await browser.close();
console.timeEnd('closeBrowser');
});
});
I've created a repository with this code and test here.
nyc _mocha ./test/*.test.js
runs in ~3500ms, mocha ./test/*.test.js
takes only 130ms.
What I've tried so far:
headless: true
What can I do to have tests with coverage be as fast as the tests alone?
Using:
Memory requirements Actors using Puppeteer: at least 1GB of memory. Large and complex sites like Google Maps: at least 4GB for optimal speed and concurrency. Working with a large amount of data in memory.
Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.
I've started to debug Puppeteer and these are my findings:
child_process.spawn()
to spawn a new browsernyc
is using spawn-wrap
for such child processesspawn-wrap
is reading the whole executable (./node_modules/puppeteer/.local-chromium/linux-686378/chrome-linux/chrome
) into memory with fs.readFileSync
which is taking an unusually long time to finishspawn-wrap
s README delivers some kind of an explanation:
The initial wrap call uses synchronous I/O. Probably you should not be using this script in any production environments anyway. Also, this will slow down child process execution by a lot, since we're adding a few layers of indirection.
For me personally the answer is that I cannot get the same performance for running tests with and without code coverage as long as I use nyc
/istanbul
.
I've given c8
a shot, and the performance is nearly the same and I can still have code coverage.
Please try this also.
'use strict'
const puppeteer = require('puppeteer')
module.exports = async function startBrowser() {
const options = {
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--single-process', // <- this one doesn't works in Windows
'--disable-gpu'
],
headless: true
}
return await puppeteer.launch(options)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With