Benchmarking Process Startup Time

Last updated: Thu Apr 22 06:34:56 AM CEST 2021

What?

Last year I bought a gaming computer and out of curiosity also installed Ubuntu on it. My main development machine is a MacBook Pro 16-inch, but for old times’ sake I tried to do some programming with the Ubuntu installation.

Now, I used Ubuntu as my main OS from 2004 to 2011, before switching to MacBooks and macOS, which I’ve been using ever since. That is to say I half-expected audio, scroll speed, mouse buttons, and printers to be, ehm, finicky.

What I didn’t expect was this:

Ubuntu feels snappier!

The machines — the MacBook and the gaming computer — have roughly the same specs, so how the same things feel instant on one and, well, laggy in comparison on the other?

What things? Short-lived processes that are not IO bound and not CPU heavy. 90% of my time developing is spent inside tmux inside Kitty; that’s where I start a lot of one-off shells, close them, run a ton of short-running commands, such as git status. All of this, including typing text into the terminal and into Neovim, feels instant on Ubuntu.

I still don’t know why. My suspicion: processes start faster on Linux and something is making them slower on macOS.

I’m using this page here to document what I find.

Setup

macOS Linux
Model MacBook Pro (16-inch, 2019)
OS macOS Catalina, Version 10.15.7 Ubuntu 20.10
Processor 2,4 Ghz 8-Core Intel Core i9 AMD Ryzen 7 5800X, 8x 3.8GHz, 32MB L3 Cache
Memory 64 GB 2667 MHz DDR4 64GB DDR4-3000 CL16, Corsair Vengeance LPX black
Graphics AMD Radeon Pro 5500M NVIDIA GeForce RTX 3070, 8GB

Benchmarks

zsh startup time

/usr/bin/time /bin/zsh -i -f -d -c 'for i in $(seq 1 500); do /bin/zsh -c "echo hello >/dev/null && exit 0"; done'

Results:

macOS Linux
Run #1 2.08s 0.38s
Run #2 2.55s 0.37s
Run #3 2.15s 0.44s
Run #4 2.11s 0.41s

git status

In sourcegraph/sourcegraph, with a clean working directory, after running git gc, on main@62cc96c96d59e8d8beffe3aca9afdc18c4a98619:

/usr/bin/time /bin/zsh -i -f -d -c 'export GIT_CONFIG_NOSYSTEM=1 && export GIT_CONFIG=/dev/null && for i in $(seq 1 100); do git status >/dev/null; done'
macOS Linux
Run #1 5.38s 0.64s
Run #2 5.21s 0.64
Run #3 5.32s 0.64
Run #4 5.29s 0.53

exit 0

// main.c

int main(int argc, char *argv[]) {
    return 0;
}

On Linux: compiled with gcc -o main main.c and then

/usr/bin/time /bin/zsh -i -f -d -c 'for i in $(seq 1 100); do /home/mrnugget/main; done'

On macOS: compiled with clang -o main main.c and then

/usr/bin/time /bin/zsh -i -f -d -c 'for i in $(seq 1 100); do /Users/thorstenball/main; done'

Results:

macOS Linux
Run #1 0.24s 0.02s
Run #2 0.21s 0.01s
Run #3 0.21s 0.02s
Run #4 0.21s 0.02s

Add number

// main.c

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    int num = atoi(argv[1]);
    printf("%d\n", num*num);
    return 0;
}

On Linux: compiled with gcc -o main main.c and then

/usr/bin/time /bin/zsh -i -f -d -c 'for i in $(seq 1 500); do /home/mrnugget/main ${i} >/dev/null; done'

On macOS: compiled with clang -o main main.c and then

/usr/bin/time /bin/zsh -i -f -d -c 'for i in $(seq 1 500); do /Users/thorstenball/main ${i} >/dev/null; done'

Results:

macOS Linux
Run #1 1.20s 0.12s
Run #2 1.47s 0.11s
Run #3 1.06s 0.11s
Run #4 1.03s 0.10s