Run it yourself
Your Mac, your clients, the same instrument
An afternoon of setup, most of it adding an account to each client and waiting for it to sync. After that, each client is one command. Everything stays on your machine until you open a pull request.
The harness clicks, types and scrolls in real windows. It never touches your own mail — the benchmark account is a separate account on a local server — but run it on a Mac you can leave alone for a while.
- 1
Get the harness
A Mac with Xcode’s command line tools (for
swiftc), Python 3.9 or later, and Homebrew. The instrument is built on your machine the first time it runs: a binary built on another machine’s macOS would be the instrument from a different experiment.git clone https://github.com/wes/mailbench.git cd mailbench xcode-select --install # if swiftc is missing brew install dovecot ./mailbench doctor # what this machine has and is missing - 2
Generate the mailbox and start the server
About ten seconds for 50,000 messages. It lands in
~/mailbench/maildir-50k, and the server checks it against the published digest every time it starts. For the larger mailbox, prefix both commands withCORPUS=250k; it runs beside the first, on port 10144../mailbench corpus 50k ./mailbench server start # Dovecot on 127.0.0.1:10143, warmed, behind the meter - 3
Grant the permissions, then calibrate
The instrument needs Screen Recording (to watch windows) and Accessibility (to post clicks and keys), granted to the terminal you run it from. Calibration measures the instrument’s own overhead on this machine and display; results without it say so.
./mailbench permissions # opens both panes in System Settings ./mailbench calibrate # about a minute; a window flips colour on its own - 4
Add the account to each client
Server
127.0.0.1, port10143, no encryption, userbench@example.com, passwordbench. Each client’s page lists what else it needs — above all, the settings that make it keep the whole mailbox locally. Let every client finish syncing before measuring it../mailbench clients # which are installed, and which are ready ./mailbench account applemail # adds it for you where the client allows; prints the steps where not - 5
Check where the clicks land
Coordinates are per client and per version, and a click two pixels off a row measures nothing. The snapshot outlines the watched rectangle in red and marks every click in blue. If they are wrong, fix the client’s JSON — and send the fix.
./mailbench snapshot mailmate - 6
Measure
One client at a time, with every other mail client quit and nothing else moving on screen. Each takes a few minutes and ends by quitting and relaunching it. Plug the Mac in, and don’t touch the mouse.
./mailbench run mailmate ./mailbench run thunderbird ./mailbench report # every client on this machine, in one table - 7
First sync (optional)
Timed at the server: empty the client’s store, follow the prompt, and the meter times the download from its first busy second to its last. It also reports what share of the mailbox the client downloaded.
./mailbench sync thunderbird - 8
Submit
submitcopies this machine’s current results intoresults/, removes your home directory from every path, writes the machine’s details, and generates the summary the site shows. It asks for your GitHub handle and whether you work on any of the clients measured — answered either way, and shown with the run../mailbench submit git checkout -b results/my-mac git add results && git commit -m "Results: <machine>, 50k" gh pr create --fill
Comparing two builds of your own client
The same harness answers “did this change make it faster?”. APP measures a particular bundle and TAG keeps its results apart, so the report puts them side by side:
TAG=before APP=~/builds/Before.app ./mailbench run myclient
TAG=after APP=~/builds/After.app ./mailbench run myclient
./mailbench reportTagged results are for you; submit the released build.
Over SSH
Nothing started over SSH can capture the screen or post input, so the commands that need either re-run themselves in Terminal on the Mac’s own display, with the display held awake, and stream their output back. Unlock the Mac first: a locked screen captures black, and the instrument refuses to run on one.
When something looks wrong
- A test reports timeouts (“14/20 runs”): a click missed its row, or the watched rectangle is not where the change happens. Run
snapshotand look. - “2 windows match”: the client has a second window open. Close it, or narrow the client’s
window_title. - The corpus is not the published one: regenerate it. A client that deleted or moved a message changes the mailbox for every client after it.
Stuck? Open an issue with the output of ./mailbench doctor. Adding a client that is not here yet is its own guide.