My first MacBook was an M3 Pro. So I never personally lived through the Intel-to-M1 moment that Mac users describe with a certain glow in their eyes. But I came from state-of-the-art Intel and Windows notebooks, and even three chip generations into Apple Silicon, the difference floored me: a laptop that is instant, silent, cool on my lap, and the battery life is notably better. My old machines could win benchmarks too. They just never felt like this.
The cleanest illustration of the jump is a machine I never owned: the 2020 MacBook Air. Apple sold it twice in the same year, in the same chassis. The early-2020 Intel version ran hot, throttled under load, and became famous because its fan was not even attached to the heatsink with a heatpipe; it mostly blew air around the case (Macworld). The late-2020 M1 version had no fan at all. Same shape, silent, cool, and roughly twice as fast in single-core and about 2.6x in multi-core in Geekbench 6 (2,347/8,341 vs. 1,197/3,150 as the averages at the time of writing, M1 Air and Intel i7 Air on Geekbench Browser). Apple’s battery rating went from 11 to 15 hours of web browsing (Intel Air, M1 Air).
Same case, one year apart, a different class of machine. How? That question turns out to be a nice tour through computer architecture, so this post became long. Every section introduces the concepts it needs, and you can stop after any of them with a correct, just less detailed, picture.
Wide beats fast: what a CPU core actually does all day
To understand the first big reason, I need to introduce how a modern CPU core is organized, because “8-wide decode” means nothing without that background.
A CPU executes a program as a stream of instructions: load this value from memory, add these two numbers, store the result, jump if the result was zero. The naive picture is that the core does these one after another, one per clock tick. Real cores stopped working like that decades ago, for two reasons.
First, pipelining. Executing one instruction involves several steps: fetch it from memory, decode what it means, execute it, write the result back. The execute step happens in the ALU (arithmetic logic unit), the circuit that actually performs the calculation; the decode step before it figures out which operation the instruction bits encode and sets the control signals accordingly, effectively wiring up the ALU in preparation for the execution. Instead of finishing one instruction completely before touching the next, the core works like an assembly line: while instruction 1 is executing, instruction 2 is being decoded and instruction 3 is being fetched. Every station of the line is busy all the time.
Second, superscalar execution. A core does not have one ALU, it has many: several integer ALUs, several floating-point/vector units, several load/store units. So it can start multiple instructions in the same clock cycle, as long as it can find instructions that do not depend on each other. This is where the term “width” comes from: a 4-wide core can feed up to four instructions per cycle into its execution units.
The catch is the phrase “do not depend on each other”. If instruction B needs the result of instruction A, B has to wait. These conflicts are called hazards, and the worst ones involve memory: a load that misses the cache and has to go to DRAM can take hundreds of cycles. In a naive in-order core, everything behind that load just stalls: hundreds of cycles are spent doing nothing but waiting for the data to arrive, while most of the core’s transistors sit idle.
The answer is out-of-order execution (OoO). The core keeps a window of upcoming instructions, in Apple’s case hundreds of them, and continuously scans it for instructions whose inputs are ready, executing those immediately even if previous instructions are still waiting. To keep the program’s illusion of sequential execution intact, results are held in a structure called the reorder buffer (ROB) and only “retired” in original program order. The bigger the ROB, the more independent work the core can find to hide the latency of a slow memory access.
One obstacle is still missing from this picture: branches. A significant share of all instructions are conditional jumps (an if, a loop condition), and until such an instruction is actually executed, the core does not know where the instruction stream continues. A pipeline that waited at every branch would be idle most of the time, and an out-of-order window of hundreds of instructions could never fill up. So the core guesses: a branch predictor learns the past behavior of each branch and predicts which way it will go, and the core speculatively fetches and executes along the predicted path as if the guess were certain. Modern predictors are right the vast majority of the time, and then the speculative work simply becomes real work. But when the guess was wrong, everything executed after the branch was work on the wrong path: the pipeline is flushed, all speculative results are discarded from the ROB, and fetching restarts at the correct target. A flush costs on the order of a dozen cycles, and the deeper and wider the core, the more work gets thrown away each time. A huge OoO window like Apple’s is therefore only worth building next to a very good branch predictor; the two sizes have to grow together.
All of this machinery has to be fed. The part of the core that fetches and decodes instructions is called the frontend, and the frontend is where instruction encoding suddenly matters. ARM64 instructions are all exactly 4 bytes long, so a decoder that wants to decode 8 instructions in parallel just looks at byte offsets 0, 4, 8, … trivially. x86 instructions are 1 to 15 bytes long, and you only know where instruction n+1 starts after you have at least partially decoded instruction n. Finding instruction boundaries is inherently serial, and x86 designs of that era paid for parallel decode with complexity and power, which is a big part of why they stopped at about 4-wide.
Now the M1 numbers have meaning. The Firestorm performance core in the M1 is 8-wide in decode, which AnandTech called “by far the widest commercialized design in the industry” at the time, with a reorder buffer of roughly 630 entries, against about 352 for Intel’s contemporary Sunny Cove and about 256 for AMD’s Zen 3 (AnandTech deep dive, archived, Dougall Johnson’s reverse engineering). The design philosophy is the opposite of the gigahertz race: instead of pushing clock frequency (which costs power roughly quadratically, because higher frequency needs higher voltage), Firestorm runs at a relaxed ~3.2 GHz and wins by keeping an enormous amount of work in flight per cycle.
And it worked. In AnandTech’s SPEC testing, this 3.2 GHz laptop core beat Intel’s new Tiger Lake mobile chips and their top-performing desktop CPU in the majority of single-threaded workloads, and traded blows with AMD’s Zen 3 desktop flagship, while the whole M1 machine drew 7-8 W of device power against the 49+ W of the Zen 3 chip alone (AnandTech M1 review, archived). That is the “faster AND cooler” paradox resolved: it is not magic, it is a fundamentally different operating point.
Eight cores, two Macs: scheduling on asymmetric cores
The second reason lives in the interplay between hardware and the operating system, so I first need to explain how an OS distributes work over cores at all.
A running program is a process, and each process has one or more threads: independent streams of execution that share the same memory. At any moment, the OS scheduler decides which thread runs on which core. The state of a running thread is surprisingly small: the CPU registers, the program counter, the stack pointer. To move a thread, the OS saves this context to memory, and any core can later load it and continue exactly where the thread stopped. This is a context switch, and it happens thousands of times per second. Threads hop between cores all day without noticing.
Because threads of one process share memory, two threads on two different cores can touch the same data. If they do so unsynchronized, you get a data race: both read the value, both modify it, one write is lost. The hardware also has to work to make shared memory look shared, because each core has private caches. When core A writes to an address that core B has cached, a cache coherence protocol (the classic textbook one is MESI) invalidates B’s copy, so B’s next read fetches the fresh value. Keep this in the back of your mind, it becomes important again in the Rosetta section.
The point of all this: cores are interchangeable workers, and the scheduler is free to place any thread anywhere, every few milliseconds. Which raises a question: what if the cores are not interchangeable or identical?
That is big.LITTLE, a concept Apple imported directly from its phone chips. The M1 has four big Firestorm performance cores (P-cores) and four small Icestorm efficiency cores (E-cores). The E-cores are much narrower and slower, but absurdly frugal: Apple claims a tenth of the power, and Howard Oakley measured the M1’s entire four-core E-cluster drawing only 160-170 mW while running background work (Eclectic Light). For comparison, that is microcontroller territory, in a desktop-class SoC.
Asymmetric cores are only useful if the scheduler knows which work belongs where. macOS solves this with Quality of Service (QoS) classes: since OS X 10.10, developers annotate work as user-interactive, user-initiated, utility, or background. On Intel Macs these classes mostly influenced priority under contention. On Apple Silicon they decide core placement, and there is deliberately no API to pin a thread to a specific core; QoS is the only knob (Apple developer docs, WWDC 2020 session on AMP).
Howard Oakley’s measurements revealed the detail I find most interesting in this whole story: on M1 Macs under macOS 11 and 12, threads marked background-QoS run exclusively on the E-cores. Not “preferably”. Exclusively, even when the E-cores are saturated and all four P-cores sit idle (Eclectic Light). Oakley’s framing is that an M1 Mac is really two Macs: one that runs macOS housekeeping (Spotlight indexing, Time Machine, backups, sync) and one that runs your apps. What unites the two is the kernel and the memory: a single scheduler controls both sets of cores, and both clusters share the same unified memory, so moving a thread between the two worlds is just an ordinary context switch, with no data to migrate. On an Intel Mac, a misbehaving background task competed with your foreground app for the same cores, and you felt it as stutter. On an M1, it physically cannot touch the cores your app is using. (This strict mapping was macOS 11/12 behavior; later versions relaxed it.)
I find this explains a lot of the subjective “it never hesitates” feeling that benchmarks do not capture. Part of the M1 experience is not that the machine is faster, but that the machine is never busy with something else when you ask it to do something.
Memory next door: what “unified memory” replaces
To appreciate unified memory, it helps to look at how a CPU traditionally talks to a discrete GPU, because that is the model Apple threw away.
In a classic PC, the GPU is effectively a second computer on a plug-in card: it has its own processor and its own memory (VRAM), connected to the rest of the system over the PCIe bus. When a program wants the GPU to do something, the data has to physically travel: the CPU prepares buffers in main memory, a DMA engine copies them over PCIe into VRAM, the GPU computes, and when it is done it announces that with an interrupt, and results get copied back the same way.
Interrupts deserve a closer look here, because they show how much machinery is involved when two chips merely want to tell each other “I’m done”. A device cannot simply call a function on the CPU; the only thing it can do is assert an electrical interrupt request (IRQ) line. An interrupt controller collects the request lines of all devices, prioritizes them, and signals the CPU. The CPU finishes its current instruction, saves enough of its state to resume later, sends an interrupt acknowledge back so the controller knows the request was taken, and then looks up who is calling in the interrupt vector table: a table that maps each interrupt number to the address of its handler routine. Only now does the actual driver code run, query the device to find out what it wants, and finally return to the interrupted program, which never noticed a thing. In the basic model, that whole round trip happens for every completed GPU job and every finished DMA transfer, and while short, it is pure overhead: no useful work gets done during it. It is so expensive, in fact, that real drivers engineer around it: they batch queued transfers into chains with a single interrupt at the end, coalesce many completions into one, or let the GPU write a completion flag into memory and poll it instead of being interrupted at all. The overhead does not disappear, it just gets amortized and dodged.
Every one of the copies costs time, and more importantly energy, because moving a bit across a board-level bus is vastly more expensive than moving it inside a package. And the whole dance is asynchronous bookkeeping: drivers, staging buffers, synchronization points, and an interrupt round trip at every step.
Integrated graphics (which Intel MacBooks also had) removes the separate card but historically still partitioned memory: a slice of RAM was carved out for the GPU, and data still got copied between the CPU’s view and the GPU’s view.
Apple’s unified memory architecture (UMA) takes the phone-SoC approach instead: the M1 has 8 or 16 GB of LPDDR4X mounted directly in the chip package, on a 128-bit bus with about 68 GB/s of bandwidth, and this single pool is shared by the CPU, the GPU, the Neural Engine, and the media engines (Apple newsroom). Sharing here means genuinely the same physical memory: the CPU produces a video frame or a texture, and the GPU reads it at the same address. No PCIe crossing, no staging copies, no partition. Apple’s WWDC session put it exactly in these terms: textures and geometry shared with no copy over a bus (WWDC 2020).
It is worth being precise about which parts of the interrupt machinery UMA removes and which it keeps. Interrupts as such stay: the GPU is still an independent processor, so “I finished the frame” is still signaled with an interrupt request, acknowledge, vector table lookup, and handler, exactly as described above. What disappears is everything the old model needed around the actual computation: the DMA copies into and out of device memory together with their completion signaling, the staging buffers, and the driver bookkeeping that managed two copies of the same data. Instead of “copy over, interrupt, compute, interrupt, copy back, interrupt”, the flow shrinks to “here is the address, compute, interrupt”. The signaling mechanism survives; the data movement it used to orchestrate is gone.
The trade-off is real and worth being honest about: the RAM is part of the chip package, so it is non-expandable, forever. And how much UMA contributes to general everyday performance (as opposed to GPU/ML workloads) is genuinely debated; I list that under open questions at the end.
The manufacturing gap
Chips are printed in generations of manufacturing technology called process nodes. A newer node means smaller transistors, and smaller transistors switch faster and waste less energy per switch, independent of any architectural cleverness.
The M1 and its iPhone sibling A14 were the first commercial chips on TSMC’s N5 node. TSMC’s own IEDM paper claims about 1.84x logic density and either +15% speed or -30% power versus the previous N7 (WikiChip on TSMC’s IEDM paper, archived). Intel, meanwhile, was still shipping most MacBook chips on its 14nm process, years after 10nm was originally due, and Intel’s 10nm class was roughly comparable to TSMC’s older 7nm. So Apple was not one node ahead, it was multiple generations of manufacturing ahead of the chips it replaced.
This matters for interpreting everything above: part of the M1’s advantage was architecture, part was simply better transistors. Nobody has cleanly decomposed the two, because you cannot buy a Firestorm core on Intel 14nm to compare. I flag this rather than hand-wave it.
The human side of the backdrop: while Intel spent five years squeezing single-digit gains out of 14nm-class products, Apple’s phone cores improved relentlessly. AnandTech calculated roughly +28% single-thread improvement for Intel over the five years before the M1, versus about +198% for Apple’s A-series in the same window, and concluded that “there simply was no other choice” for Apple than to leave Intel (AnandTech, archived).
Deep dive: the M1 is a phone chip scaled up, not a desktop chip shrunk down
I think this is the most underrated part of the whole answer: the M1 did not appear out of nowhere in 2020. It is the product of a ten-year chip lineage that matured in everyone’s pocket.
Apple started designing its own SoCs after acquiring the chip design company PA Semi in 2008. The A4 (2010, first iPad and iPhone 4) was the first chip with Apple’s name on it, though it still used a licensed ARM Cortex-A8 core; Apple’s first fully custom core arrived with the A6 in 2012.
The inflection point was the A7 “Cyclone” in 2013: the first 64-bit ARM chip in any smartphone, a full year before competitors. When AnandTech dug into it (partly via Apple’s own LLVM compiler commits), they found a 6-wide core with a 192-entry reorder buffer. For reference, 192 entries was exactly the ROB size of Intel’s then-current desktop core, Haswell. AnandTech’s conclusion at the time was that Apple’s internal “desktop-class” label was no exaggeration (AnandTech on Cyclone, archived). A Qualcomm insider later described the A7 as a punch in the gut. Read that again with today’s knowledge: Apple was shipping a small desktop-class CPU in a phone, seven years before the M1. The entire time the Mac was waiting on Intel’s roadmap, the solution was maturing in everyone’s pocket.
From there it was annual iteration on an unforgiving power budget (a phone has no fan and a tiny battery, so every milliwatt counts), until the A14 in late 2020. And here the transition becomes concrete, because the A14 and the M1 share the same Firestorm and Icestorm cores. The scaling step from phone chip to Mac chip was:
- A14: 2 P-cores + 4 E-cores, 11.8 billion transistors, for a iPhone 12.
- M1: 4 P-cores + 4 E-cores, 16 billion transistors, higher clocks (~3.2 GHz), a 50% bigger shared P-core L2 cache (12 MB), double the memory bus width, and a bigger GPU.
That is it. More copies of the same cores, more cache, more memory bandwidth, all enabled by a laptop’s bigger power budget. The A14’s SPEC results already competed with the best x86 designs before the M1 even shipped, which AnandTech called “just an astonishing feat” (AnandTech, archived). The M1 was not a bold new design; it was the routine annual iteration of a ten-year lineage, aimed at a new target. That is also why it landed with such confidence: Apple had shipped this core design, in volume, in hundreds of millions of devices, before the first MacBook got it.
Deep dive: Rosetta 2, or how emulated x86 beat real x86
The transition had an obvious fatal risk: every existing Mac app was compiled for x86, and an ARM chip cannot execute x86 instructions. Apple’s answer was Rosetta 2, and it is my favorite piece of the whole story, because the solution reaches all the way down into the silicon.
First, what “translation” means here. An x86 binary is a sequence of x86 instructions; an ARM CPU needs ARM instructions. A translator reads the x86 machine code and emits equivalent ARM machine code. You can do this just-in-time (JIT), translating code the moment it is about to run (this is what browsers do with JavaScript), or ahead-of-time (AOT), translating the whole program once before it runs. Rosetta 2 is primarily AOT: at first launch (or install), the entire executable is translated, and the result is cached on disk as a signed binary, so the cost is paid once (Apple docs, Project Champollion teardown). A JIT path exists as a fallback for programs that generate code at runtime.
AOT translation with a near 1:1 instruction mapping (Dougall Johnson measured only about 1.64x code expansion for sqlite3) keeps the translated code cache-friendly and predictable (Why is Rosetta 2 fast?). But two hard problems remain, and both were solved in hardware.
Problem 1: condition flags. x86 arithmetic instructions set six status flags, including odd ones like a parity flag; ARM sets four and no parity. Faithfully emulating the x86 flags in software costs several extra ARM instructions after every arithmetic operation. Apple’s silicon has an undocumented extension: a mode in which ADDS/SUBS/CMP additionally compute x86’s parity and adjust flags into spare bits of the flags register. Think about what that means physically: the ALUs of every M1 include the calculation circuits for x86’s flag semantics in silicon, disabled by default, waiting for the kernel to switch them on for a translated process. Exact x86 flag semantics, zero extra instructions (Dougall Johnson).
Problem 2: memory ordering. This one connects back to the cache coherence section. A memory model defines what one thread is allowed to observe about another thread’s memory writes. x86 guarantees Total Store Ordering (TSO): stores become visible to other cores in program order. ARM’s model is weaker: the hardware may make writes visible in a different order, and correctly synchronized ARM programs insert explicit barrier instructions where ordering matters. This weakness is not sloppiness, it is an enabler: the fewer ordering guarantees the memory model makes, the more freedom the out-of-order machinery has to reorder loads and stores around slow memory accesses, instead of spending effort on preserving an ordering appearance that single-threaded code never notices anyway. The measurement below quantifies exactly this freedom. Now translate a multithreaded x86 binary: the original code contains no barriers, because x86 never needed them, but its correctness may silently depend on TSO. A naive translator must conservatively sprinkle barriers around memory accesses, which is expensive.
Apple’s solution: the M1 has a hardware TSO mode, a per-thread bit (in the ACTLR_EL1 register, context-switched by the kernel) that makes ordinary ARM loads and stores obey x86 ordering. Translated code runs with the bit set, native code runs without it. The Asahi Linux community reverse-engineered this, and Hector Martin submitted Linux patches for it in 2024 (rejected upstream, for the record); Apple itself has since officially documented TSO as a feature, exposing it to Linux VMs for exactly this use case (Apple Virtualization docs). A peer-reviewed study later measured what this ordering mode intrinsically costs: on an M1 Ultra under Asahi Linux, the same native ARM binaries (SPEC CPU 2017’s parallel floating-point suite) ran on average 8.9% slower with the TSO bit set than with ARM’s weak ordering, ranging from no effect at all to about 20% depending on the workload (TOSTING, ARCS 2023). Note what that number is: the price of the ordering mode itself, measured on native code, not the overhead of translated x86. The software alternative is much worse; existing x86 emulators like QEMU conservatively insert a fence after basically every memory instruction, and the paper’s own comparison of explicitly-ordered instructions suggests that costs up to twice the throughput in the worst cases. That is why this bit exists.
There is a beautiful symbiosis here that Dougall Johnson points out: translation inflates the instruction count, and Firestorm’s extreme width (section one) is exactly what absorbs that inflation without becoming throughput-bound. The wide core makes the translator viable; the translator makes the transition viable.
The punchline: at launch, Rosetta-translated x86 code ran at roughly 78-79% of native M1 speed in Geekbench 5, and that translated single-core score still beat every Intel Mac Apple had ever sold, including the contemporary Core i9 iMac (MacRumors). Emulated x86 on the M1 was faster than real x86 on Intel Macs. Day-one users kept their old apps and still got a speedup. (The ~78% figure is workload-dependent: when the native M1 version of Chrome arrived a week later, it beat its own Rosetta-translated predecessor by 66-81% in browser benchmarks, meaning the translated browser had been running at only 55-60% of native speed (MacRumors on the Ars Technica tests).)
What is still argued
Two debates I read up on and deliberately leave open, because the experts have not settled them and I cannot resolve them from my armchair:
Does the ISA itself actually matter? I presented fixed-length ARM decode as an enabler of the 8-wide frontend, and that argument is real. But the counter-position has serious backing. A peer-reviewed measurement study compared ARM and x86 processors across mobile, desktop, and server workloads and concluded that “ARM and x86 processors are simply engineering design points optimized for different levels of performance, and there is nothing fundamentally more energy efficient in one ISA class or the other” (Blem et al., HPCA 2013). Having read the paper, I would add its own honest scope limits: the widest core it tested was a 4-wide Sandy Bridge in 2013, it never directly measured decoder power, and it explicitly concedes that x86 forces larger out-of-order structures while scoping its conclusion to “these performance levels”. Whether the result extends to an 8-wide design like Firestorm is precisely the part that remains open. Jim Keller, who led CPU designs at DEC, AMD, Apple, Tesla, and Intel, called arguing about instruction sets “a very sad story”, noting that 80% of core execution boils down to six instructions anyway (AnandTech interview, archived). Modern measurements put x86 decode overhead in the single-digit percent range of core power (Chips and Cheese). In this camp’s view, Apple’s advantage is microarchitecture and process, and an equally wide x86 core is merely harder, not impossible (Intel and AMD have since built wider x86 decoders). I lean towards “the ISA made the wide frontend cheaper to build, and cheap matters”, but I hold that opinion loosely.
How much of Rosetta 2’s speed is the TSO hardware? The developers of the FEX emulator (which runs x86 on ARM, historically without Apple’s TSO bit) write that “emulating the x86 memory model is the number one thing” slowing their emulation down, which suggests the bit is crucial (FEX release notes). The other camp holds that most of Rosetta’s speed comes from AOT translation, register mapping, and the sheer width of the core, with the hardware modes as supporting tricks; Dougall Johnson’s teardown, which walks through all of these factors, reads much more like this second story (Why is Rosetta 2 fast?). Both camps cite the same ~8.9% TSO measurement in opposite directions, and having read the paper, I think that is fair: it quantified the hardware mode’s cost on native ARM binaries but never measured software-emulated TSO or translated x86 code head-to-head, so it genuinely does not settle this question.
Closing: the playbook got copied
The most telling epilogue is what the competition did next. Intel’s Lunar Lake chips (2024) put LPDDR5X memory directly on the package (TechPowerUp), overhauled their efficiency cores, and, remarkably, are manufactured not in Intel’s own fabs but at TSMC, on a 3nm-class node. The reviews split on whether it fully caught up to Apple’s contemporary chips, but the direction is unambiguous: the response to the M1 was to adopt its playbook (XDA analysis).
Which, to me, is the actual answer to this post’s title question. The M1 did not feel huge because of any single trick. It felt huge because Apple moved every lever at once: the widest core in the industry, on the best process node in the industry, with memory in the package, efficiency cores doing the housekeeping, an OS scheduler that knows about all of it, and a translation layer with dedicated silicon support so that nobody had to wait for the ecosystem to catch up. Any single one of these would have made a nice bullet point in a keynote. Together, and only together, they made a laptop that felt like a different kind of machine. That is what ten years of building phone chips on a merciless power budget teaches you.
One loose end has thoroughly caught my interest, though. Everything in this post, from Apple’s Neural Engine and media engines to Intel’s copied playbook, follows the same doctrine: chip power limits mean not every transistor can be powered at the same time anyway, so you fill the die with specialized blocks and only light up the one that fits the current task. A German startup called Ubitium is betting that the pendulum can swing back: a single reconfigurable array of RISC-V processing elements that switches execution mode at runtime, between CPU-style out-of-order execution, DSP-style loop acceleration, and GPU-style threading, replacing CPU, GPU, DSP, and FPGA with the very same transistors (Ubitium). Their first chip taped out on Samsung’s 8nm process in December 2025 (announcement), and the idea has real depth behind it: the IP traces through two decades of reconfigurable-computing work by their CTO Martin Vorbach, from PACT XPP to a granted patent on the core architecture (US11797474B2), which describes arrays of ALUs where every element can execute a different instruction, and where instructions, once issued, can stay in place for many cycles while the data streams through them. Whether one universal fabric can undo the fracturing of the computer into many specialized computers is a whole different rabbit hole, and I will climb into it in another post.