Benchmarking web dev tools on the Mac mini M1
Tags: webdev, performance
Published: 2020-12-13 07:44:23

In the weeks after the new Apple Silicon Macs were launched there were plenty of reviews with benchmarks for tasks like video encoding, 3D rendering and so on. However I couldn't find anything testing the web development tools that I use every day, such as Node, Babel and TypeScript. A lot of the M1's speed comes from specialised cores, so there was a risk that it would not be as fast for web development. In the end I decided to risk it and order one and run some benchmarks myself.

I'd been looking for something to use as a headless compilation machine for a while. I'm an engineer on the Gatsby open source team, and have to compile the massive monorepo many times a day. We do a lot of a pair programming over Zoom, and that's particularly difficult when compiling. VS Code [remote development](https://code.visualstudio.com/docs/remote/) is very slick, so when the M1 Macs were released, a Mac mini seemed just the job. I needn't have worried: the Mac mini M1 comfortably beats my Macbook Pro in every task I threw at it. This includes benchmarks, but also real world development tasks.

## Test setup

I ordered the entry level Mac mini with 8GB of RAM, and my comparisons are with my work machine: a Late 2019 16" Macbook Pro 2.3GHz core i9 with 16GB of RAM. For my initial tests I used the [V8 Web Tooling Benchmark](https://github.com/v8/web-tooling-benchmark/). This uses Node to run several realistic tasks, using the sort of tools web developers use every day: Babel transpilation, and various other parsers, TypeScript, PostCSS, Prettier, ESLint and more. The benchmark itself is three years old, and uses old versions of these tools. It can run on the latest Node though, and should still be representative of the relative speeds.

To run the tests, I first installed Node 15.4.0 using Homebrew on the mini and using nvm on the MBP. I made sure that it was running natively by using the Node REPL to check `process.arch`. It will be `arch64` if it's a native build, and `x64` if running the Intel version using Rosetta2. I ran the benchmarks according to the instructions: `npm install`, `npm build` then `node dist/cli.js`. I ran the benchmarks several times to be sure they weren't outliers.

## Results

[V8 Web Tooling Benchmark](https://github.com/v8/web-tooling-benchmark/). Higher scores are better

### Mac mini M1

```
Running Web Tooling Benchmark v0.5.3…
-------------------------------------
         acorn: 21.29 runs/s
         babel: 14.64 runs/s
  babel-minify: 20.82 runs/s
       babylon: 21.11 runs/s
         buble: 10.25 runs/s
          chai: 27.62 runs/s
  coffeescript: 14.24 runs/s
        espree:  4.07 runs/s
       esprima: 15.86 runs/s
        jshint: 18.65 runs/s
         lebab: 18.26 runs/s
       postcss: 10.97 runs/s
       prepack: 15.17 runs/s
      prettier: 11.85 runs/s
    source-map: 16.93 runs/s
        terser: 35.89 runs/s
    typescript: 17.13 runs/s
     uglify-js: 11.56 runs/s
-------------------------------------
Geometric mean: 15.57 runs/s
```
### 2019 Macbook Pro 2.3GHz core i9

```
Running Web Tooling Benchmark v0.5.3…
-------------------------------------
         acorn:  9.80 runs/s
         babel:  9.04 runs/s
  babel-minify: 12.95 runs/s
       babylon: 12.37 runs/s
         buble:  6.21 runs/s
          chai: 18.01 runs/s
  coffeescript:  9.25 runs/s
        espree:  4.32 runs/s
       esprima: 10.14 runs/s
        jshint: 12.10 runs/s
         lebab: 13.86 runs/s
       postcss:  8.55 runs/s
       prepack:  9.06 runs/s
      prettier:  8.69 runs/s
    source-map: 11.68 runs/s
        terser: 20.48 runs/s
    typescript: 10.34 runs/s
     uglify-js:  6.61 runs/s
-------------------------------------
Geometric mean: 10.10 runs/s
```

The Mac mini M1 is consistently around 50% faster than the Macbook Pro in the Web Tooling Benchmark.

These are native speeds, with an arm64 build of Node. However neither Node.js nor Homebrew offically support Apple Silicon yet, and many native npm packages need to compile from source. There are many cases where you may need to run x64 tools using Rosetta2. This is inevitably going to be slower than native, but the good news is that it's still faster than the Macbook Pro.

### Mac mini M1, via Rosetta2
```
Running Web Tooling Benchmark v0.5.3…
-------------------------------------
         acorn: 15.34 runs/s
         babel: 11.84 runs/s
  babel-minify: 15.46 runs/s
       babylon: 14.56 runs/s
         buble:  7.93 runs/s
          chai: 22.66 runs/s
  coffeescript: 11.60 runs/s
        espree:  5.51 runs/s
       esprima: 14.44 runs/s
        jshint: 15.92 runs/s
         lebab: 15.15 runs/s
       postcss: 10.44 runs/s
       prepack: 12.23 runs/s
      prettier:  9.76 runs/s
    source-map: 16.78 runs/s
        terser: 24.10 runs/s
    typescript: 10.36 runs/s
     uglify-js:  7.94 runs/s
-------------------------------------
Geometric mean: 12.64 runs/s
```
Even via Rosetta the Mac mini is around 25% faster than the Macbook Pro.

## Real-world tests

While the benchmark seems to be representative of real-world web development tasks, I still needed to compare with my day-to-day tasks. If anything, the lead is even more there.

Running `lerna bootstrap` in a clean [gatsby monorepo](https://github.com/gatsbyjs/gatsby). This runs `yarn install` in the root of the monorepo, then `yarn install` across all 112 packages, and then `yarn prepare` which builds each of them and prepares it for publishing. Most packages are compiled with Babel, but some are compiled with the TypeScript compiler, and some of the Babel ones have TypeScript types generated. Some packages are bundled with microbundle or rollup. There's even a Gatsby site in there (the gatsby-admin app). It's a generally tough but representative sample. Lower times are obviously better!

- Macbook Pro: 4 mins, 33 seconds
- Mac mini M1: 2 mins, 45 seconds

This was run simultaneously on both machines (using iTerm input broadcasting), with both on the same network.

One thing I noticed while running it was that the yarn install was noticably faster on the mini, which I put down to faster disk IO. To see the other side of disk IO that most web developers need to do, I checked this by running `rm -rf node_modules`!

![screenshot of running rm-rf node_modules packages/*/node_modules](https://dev-to-uploads.s3.amazonaws.com/i/79rw85yef1k3v17orgc4.jpg)

I tried several other tasks, such as running the `gatsby-dev-cli` which publishes all gatsby packages to a local npm server, and then installs those in a site for testing. Each of them was considerably faster with the Mac mini.

## Conclusion

As I'm using mine as a remote compilation machine I haven't run tests on other apps, but there are plenty of other reviews that have. Based on my tests, the M1 Macs are incredibly fast for web development, and are an absolute bargain too. This was a bottom of the range Mac mini comfortably beating a top of the range Macbook Pro that's just a year old and cost four times as much.