cat posts/2020-11-24-apple-m1-an-x86-lifers-first-week-on-arm.md

Apple M1: an x86 lifer's first week on ARM

· 5 min read · apple arm hardware tools macos

The fan is the first thing I noticed, or rather that there isn’t one. The M1 MacBook Air has no fan at all, and I spent the first evening running builds on it and waiting for it to get hot, the way my Intel MacBook Pro sounds like it’s about to take off whenever webpack starts. It got slightly warm. That was it.

It arrived last Tuesday, the first day they shipped, a week after Apple announced the M1 on the 10th. I’ve used it as my main work machine since Wednesday. I want to write down my impressions now, before I get used to it, because I suspect a lot of this will seem normal in a year.

Some context on why this is a big deal for me personally. Every computer I’ve written serious code on has been x86, starting with DOS machines in the early ’90s, Clipper and Turbo C on whatever PC I could get time on. The exception is the Windows CE devices I wrote mobile apps for, which were ARM or MIPS or SH-3 depending on the year and the vendor, and every one of those taught me that porting to a different CPU is a lot of small miseries. So I came into this expecting a week of small miseries.

Rosetta 2

Most of them didn’t happen, and the reason is Rosetta 2. Anything compiled for Intel that you try to run gets translated to ARM, mostly ahead of time when you first launch or install it, with a fallback that translates on the fly for things like JIT compilers that generate code while they run. You don’t do anything. The first launch of an Intel app takes a few extra seconds while it translates, and then it just runs.

And it runs fast. The early Geekbench numbers people posted had Rosetta getting roughly 78 to 79% of native M1 performance, and the single-core score under translation still beat every Intel Mac Apple sells. That matched what I saw. Our front-end build, which is all Node and runs under Rosetta because I installed the Intel Node to start with, takes about 58 seconds on the Air. On my 2018 MacBook Pro it takes about 71. Translated code on a fanless laptop is faster than native code on the machine I paid a lot more for two years ago. I’ve run it a dozen times because I didn’t believe it.

Which isn’t to say everything works. A couple of command-line tools I depend on crashed on first run, both because they used AVX vector instructions, which Rosetta doesn’t translate, and both had native ARM builds within a few days, because their maintainers are clearly having the same week I am. Anything that’s a kernel extension or a virtualization driver is out, Rosetta doesn’t translate those.

The toolchain, as of this week

Homebrew is the messy part right now. It doesn’t fully support Apple Silicon natively yet, and the advice in their GitHub issue is to run it under Rosetta, which you do by launching your terminal as an Intel process. A native Homebrew install goes in /opt/homebrew instead of /usr/local, so you can have both side by side, and I currently have both side by side, and I’ve already once installed something into the wrong one and spent ten minutes wondering where it went.

VS Code runs under Rosetta and is fine. It’s an Electron app, and Electron only just shipped Apple Silicon support, so I’d expect a native build soon. Git, ssh and the shell are native because Apple ships them with the OS. .NET runs under Rosetta well enough to build and run the tests for our .NET services, and Microsoft has said native support is coming later. Go says it’ll support the M1 natively in February, with Go 1.16, and Rust has a target for it in nightly.

Docker is the big one. There is no Docker Desktop for the M1. Docker’s blog post last week was clear that they’re working on it and that it’s real work, since Docker Desktop on the Mac runs a Linux VM, and that needs Apple’s new virtualization framework and ARM Linux images. Our whole local development setup for the backend is a docker-compose file, so on the Air I can’t run our backend locally at all.

My workaround is a Linux dev box in our AWS account, with VS Code’s Remote-SSH extension connected to it. The editor runs locally, everything else runs there, and honestly it’s working well, partly because I’ve been meaning to try that setup for a year. But if your job is “run 12 containers on your laptop”, I’d wait.

Same for Windows. There’s no Boot Camp on these Macs, and neither Parallels nor VMware has a version that runs on the M1 yet, though both say they’re working on it. Even when they do, it’ll have to be the ARM version of Windows. As someone who’s spent a good chunk of his career in the Windows SDK, that one stings a bit. I’m keeping a Windows laptop on the desk for now.

The battery

I don’t usually care about laptop battery life, because I don’t usually go anywhere. Even so. Yesterday I worked from 8:30 to just after 5 on battery, with Slack, Chrome, VS Code over SSH, four Zoom calls and a few builds, and it finished the day at 41%. My MacBook Pro would have been dead by early afternoon on the same day, and hot the whole time.

I’m a lot less sure what it means more broadly. Apple has done something that Intel and AMD don’t seem to have an answer for this year, and the M1 is their low-end chip, in their cheapest laptop. I’d expect the bigger machines next year to be more interesting still. Whether that moves the rest of the industry toward ARM, servers included, I really don’t know. AWS has been pushing its own ARM chips, the Graviton2 instances, and I’ve been meaning to try moving some of our stateless services onto them. A week with this laptop moved that up my list.

For now my advice to developers is roughly: if your work is mostly native Mac stuff, web front-end, or anything that runs in a terminal, buy one, Rosetta will cover the gaps. If your work depends on Docker or on running Windows locally, give it a few months.