Composer is the number one Dependency Manager for PHP, It's about to turn 8 years old, and the second major release is coming out!

Bringing in more features, better performance, while keeping compatibility with your pre-existing workflow.

Performance

One of the first things you would notice when upgrading to Composer 2 is that it is much faster than v1.

This is thanks to parallel download of packages and metadata.

How much faster?

Benchmark

For this benchmark, we are going to try and install dependencies for a small Symfony application.

The tool used in this benchmark is hyperfine, a rust command-line benchmarking tool.

We will run the benchmark on PHP 7.3, 7.4, and 8.0-beta, so we can have a better insight on the improvements.

We will use the 1.10.13 release of Composer 1, and 2.0.0-RC1 for Composer 2.

❯ composer --version
Composer version 1.10.13 2020-09-09 11:46:34

❯ composer2 --version
Composer version 2.0.0-RC1 2020-09-10 15:39:45

~/Projects/benchmarks
❯ 

The first setup would be of course to clone our repository.

❯ gh repo clone azjezz/symfony-boilerplate composer
Cloning into 'composer'...
remote: Enumerating objects: 396, done.
remote: Counting objects: 100% (396/396), done.
remote: Compressing objects: 100% (243/243), done.
remote: Total 396 (delta 180), reused 327 (delta 122), pack-reused 0
Receiving objects: 100% (396/396), 247.45 KiB | 281.00 KiB/s, done.
Resolving deltas: 100% (180/180), done.

❯ cd composer

~/Projects/benchmarks/composer develop
❯

For our test, we are going to pass 3 different options to composer when installing dependencies:

  • --ignore-platform-reqs to ensure that composer does not fail when using php 7.3 and php 8.0-beta as the project requires php 7.4
  • --no-cache to ensure that composer does not use local cache
  • --no-scripts to ensure that composer does not run post-install scripts that might sabotage the benchmark result.
❯ OPTS='--ignore-platform-reqs --no-cache --no-scripts'

~/Projects/benchmarks/composer develop
❯
❯ php --version
PHP 7.3.20 (cli) (built: Jul 20 2020 14:32:38) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.20, Copyright (c) 1998-2018 Zend Technologies

❯ hyperfine --runs 5 "composer install $OPTS" "composer2 install $OPTS" -p 'rm vendor -rf'
Benchmark #1: composer install --ignore-platform-reqs --no-cache --no-scripts
  Time (mean ± σ):     86.054 s ±  7.828 s    [User: 2.721 s, System: 1.387 s]
  Range (min … max):   79.761 s … 95.285 s    5 runs

Benchmark #2: composer2 install --ignore-platform-reqs --no-cache --no-scripts
  Time (mean ± σ):     44.043 s ±  5.979 s    [User: 4.184 s, System: 2.074 s]
  Range (min … max):   38.734 s … 51.462 s    5 runs

Summary
  'composer2 install [...]' ran 1.95 ± 0.32 times faster than 'composer install [...]'

~/Projects/benchmarks/composer develop
❯
❯ php --version
PHP 7.4.8 (cli) (built: Jul 17 2020 17:13:14) ( ZTS DEBUG GCOV )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

❯ hyperfine --runs 5 "composer install $OPTS" "composer2 install $OPTS" -p 'rm vendor -rf'
Benchmark #1: composer install --ignore-platform-reqs --no-cache --no-scripts
  Time (mean ± σ):     92.589 s ±  3.226 s    [User: 9.960 s, System: 6.585 s]
  Range (min … max):   89.983 s … 97.664 s    5 runs

Benchmark #2: composer2 install --ignore-platform-reqs --no-cache --no-scripts
  Time (mean ± σ):     57.402 s ±  2.082 s    [User: 15.724 s, System: 10.817 s]
  Range (min … max):   53.807 s … 58.836 s    5 runs

Summary
  'composer2 install [...]' ran 1.61 ± 0.08 times faster than 'composer install [...]'

~/Projects/benchmarks/composer develop
❯
❯ php --version
PHP 8.0.0-dev (cli) (built: Sep  9 2020 17:26:12) ( NTS DEBUG GCOV )
Copyright (c) The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies

❯ hyperfine --runs 5 "composer install $OPTS" "composer2 install $OPTS" -p 'rm vendor -rf'
Benchmark #1: composer install --ignore-platform-reqs --no-cache --no-scripts
  Time (mean ± σ):     88.870 s ±  1.857 s    [User: 7.997 s, System: 7.312 s]
  Range (min … max):   85.770 s … 90.725 s    5 runs

Benchmark #2: composer2 install --ignore-platform-reqs --no-cache --no-scripts
  Time (mean ± σ):     54.801 s ±  5.322 s    [User: 12.019 s, System: 10.870 s]
  Range (min … max):   49.549 s … 61.305 s    5 runs

Summary
  'composer2 install [...]' ran 1.62 ± 0.16 times faster than 'composer install [...]'

~/Projects/benchmarks/composer develop
❯

When curl extension is present, Composer 2 will download multiple packages at the same time, make use of HTTP/2, and share TLS sessions and DNS responses between HTTP requests to speed up downloads.

It must be noted that parallel download can already be achieved with Composer 1 using the symfony/flex plugin, but you will still lack the other optimizations.

Offline support

Composer 2 allows you to disable network and rely completely on cache when possible: this is great if you have a slow internet connection, or you wanna run benchmarks.

To disable network for composer 2, you must set the environment variable COMPOSER_DISABLE_NETWORK to 1, and composer.lock must be present in the current directory alongside composer.json.

Note: this disabled network completely for composer, not work as a fallback mechanism.

Root confirmation

Since version 1, composer warned users about its usage under root, as it might lead to security issues.

This is due to Composer plugins being able to execute code while installing packages, or updating.

You can read more about the issues you might encounter under root in composer at: https://getcomposer.org/root.

Composer 2 takes this to the next level by asking users to confirm if they really want to use `root` privileges and waits for their answer.

You can tell Composer not to ask for confirmation under sudo by using the `--no-interaction` / `--n` option.