Work in progress
I recently made a claim on Twitter that yarn
is still significantly faster than npm
for installing NodeJS dependencies.
My belief here was based on some light research I did near the end of 2017, not too long after NPM 5 was released claiming huge speed improvements. I found a blog post at the time claiming Yarn was still faster, and then did some light testing which confirmed this for me, by a large margin.
However, my assertion was challenged:
That’s interesting, on my project npm is ~twice as fast. I’ve not done extensive testing but it’s usually pretty clear, and running npm ci instead of npm i is another factor of 2 speed increase. Even with this the fastest install times are 2-3 minutes, our project is big 🙃
And so I'm now testing my assumption to see how NPM's speed compares to Yarn nowadays.
Coming soon
I'm running this on a Thinkpad T480 20L5, with the following stats:
OS: Ubuntu 18.04.2 LTS (64-bit)
Memory: 31.3 GiB
Processor: Intel® Core™ i7-8650U CPU @ 1.90GHz × 8
Graphics: Intel® UHD Graphics 620 (Kabylake GT2) (onboard)
Disk: 304.1 GB
I installed nodejs
version 11.14.0
and npm
version 6.7.0
from nodesource as per the official recommendation.
I installed yarn
version 1.15.2
from dl.yarnpkg.com
as per their official instructions.
I'm on a pretty stable 4G mobile connection. I tested the speed with Ookla Speedtest and got:
Ping: 22
Download: 119.12 Mbps
Upload: 23.11 Mbps
I'll restart my computer, and the only foreground applications I'll run are the terminal and Visual Studio Code, for taking notes.
I'm going to test installing dependencies from the master
branch of two of our most significant open-source website projects:
- www.ubuntu.com, currently at 6a3caaa, has a modest 3
dependencies
and 13devDependencies
- snapcraft.io, currently at f73e501, has 55
dependencies
and nodevDependencies
I'm going to test the following cases with both yarn
and npm
. In each case, I'll run the same test 3 times for each tool, alternating tools between each test.
I first run the test on the www.ubuntu.com codebase (package.json), and then with snapcraft.io (package.json).
Before each test:
# Clear out local dependencies, lockfiles and package caches
$ rm -rf node_modules/ yarn.lock package-lock.json && yarn cache clean --force && npm cache clean --force
And then I run either time yarn install
or time npm install
.
Before the first run:
# Install dependencies from scratch with both tools to warm the cache
$ rm -rf node_modules/ yarn.lock package-lock.json && yarn install
$ rm -rf node_modules/ yarn.lock package-lock.json && npm install
Before each run:
# Before each run, delete dependencies and lockfiles
$ rm -rf node_modules/ yarn.lock package-lock.json
Then I run either time yarn install
or time npm install
.
Run install
again, with no dependencies, but with a lockfile.
Before first run:
# Generate both lockfiles
$ yarn install && npm install
Before each run:
# Remove node_modules
$ rm -rf node_modules
Then I run either time yarn install
or time npm install
.
Run install
again, with all dependencies already installed, but with no lockfile.
Before each run:
# Install dependencies with the relevant tool, and remove lockfile
$ rm -rf node_modules && yarn install && rm yarn.lock
# Or
$ rm -rf node_modules && npm install && rm package-lock.json
Then I run either time yarn install
or time npm install
.
Run install
again, with all dependencies already installed.
So I first run the install without testing the time, to ensure dependencies are installed exactly as expected, and then run it again, to see how long it takes when no changes are needed.
$ yarn install && time yarn install
# or
$ npm install && time npm install
time yarn install
#1: 28.096 secondstime npm install
#1: 22.234 secondstime yarn install
#2: 24.226 secondstime npm install
#2: 18.710 secondstime yarn install
#3: 27.061 secondstime npm install
#3: 19.954 seconds
Summary
yarn install
times: Mean 26.461 seconds, variance 2.6762npm install
times: Mean 20.2993 seconds, variance 2.1294
time yarn install
#1: 46.054 secondstime npm install
#1: 38.101 secondstime yarn install
#2: 40.380 secondstime npm install
#2: 38.131 secondstime yarn install
#3: 42.527 secondstime npm install
#3: 37.868 seconds
Summary
yarn install
times: Mean 42.987 seconds, 5.4715 variancenpm install
times: Mean 38.0333 seconds, 0.0138 variance
npm
wins. Here's the log.
time yarn install
#1: 19.143 secondstime npm install
#1: 11.838 secondstime yarn install
#2: 20.621 secondstime npm install
#2: 14.741 secondstime yarn install
#3: 16.729 secondstime npm install
#3: 10.688 seconds
Summary
yarn install
times: Mean 18.831 seconds, variance 2.5733npm install
times: Mean 12.4223 seconds, variance 2.9085
time yarn install
#1: 23.009 secondstime npm install
#1: 14.305 secondstime yarn install
#2: 24.369 secondstime npm install
#2: 14.666 secondstime yarn install
#3: 23.506 secondstime npm install
#3: 14.234 seconds
Summary
yarn install
times: Mean 23.628 seconds, 0.3157 (1.336%) variancenpm install
times: Mean 14.4017 seconds, 0.0357 (0.248%) variance
npm
wins. Here's the log.
time yarn install
#1: 6.649 secondstime npm install
#1: 8.640 secondstime yarn install
#2: 6.862 secondstime npm install
#2: 8.497 secondstime yarn install
#3: 6.953 secondstime npm install
#3: 8.653 seconds
Summary
yarn install
times: Mean 6.8213, variance 0.0162npm install
times: Mean 8.5967, variance 0.0050
time yarn install
#1: 7.683 secondstime npm install
#1: 12.098 secondstime yarn install
#2: 7.645 secondstime npm install
#2: 12.156 secondstime yarn install
#3: 7.685 secondstime npm install
#3: 12.095 seconds
Summary
yarn install
times: Mean 7.671 seconds, 0.0003 (0.004%) variancenpm install
times: Mean 12.1163 seconds, 0.0008 (0.007%) variance
yarn
wins. Here's the log.
time yarn install
#1: 13.483 secondstime npm install
#1: 4.983 secondstime yarn install
#2: 11.817 secondstime npm install
#2: 4.660 secondstime yarn install
#3: 12.767 secondstime npm install
#3: 4.456 seconds
Summary
yarn install
times: Mean 12.689, variance 0.4656npm install
times: Mean 4.6997, variance 0.0470
time yarn install
#1: 19.142 secondstime npm install
#1: 6.688 secondstime yarn install
#2: 17.503 secondstime npm install
#2: 6.181 secondstime yarn install
#3: 21.810 secondstime npm install
#3: 6.263 seconds
Summary
yarn install
times: Mean 19.485 seconds, 3.1505 (16.17%) variancenpm install
times: Mean 6.3773 seconds, 0.0494 (0.77%) variance
npm
wins. Here's the log.
yarn install && time yarn install
#1: 0.584 secondsnpm install && time npm install
#1: 4.415 secondsyarn install && time yarn install
#2: 0.547 secondsnpm install && time npm install
#2: 4.816 secondsyarn install && time yarn install
#3: 0.555 secondsnpm install && time npm install
#3: 4.406 seconds
Summary
yarn install
times: Mean 0.562, variance 0.0003npm install
times: Mean 4.5457, variance 0.0366
yarn install && time yarn install
#1: 0.640 secondsnpm install && time npm install
#1: 6.737 secondsyarn install && time yarn install
#2: 0.669 secondsnpm install && time npm install
#2: 6.692 secondsyarn install && time yarn install
#3: 0.660 secondsnpm install && time npm install
#3: 6.599 seconds
Summary
yarn install
times: Mean 0.6563, 0.0001 (0.02%) variancenpm install
times: Mean 6.676, 0.0033 (0.05%) variance
yarn
wins. Here's the log.
If you want to know more about where Yarn spends most of its time, you can through the hidden hooks. Just create a js file that contains the following (replace
./yarn.js
by the actual path to the Yarn release):The other enumeration values also work and should print the individual times for each respective step for the install. I'm curious to see where we spend the most time.
In theory the fetch time 0 should be zero with a cache, and the resolve step should be 0 with a lockfile. The link time is a bit weird an not as much optimized as it could (which is why we came up with Plug'n'Play).