Ch8.10: Why “Zero‑Overhead” and “Zero‑Cost” Are Meaningless
Overview
The phrases “zero‑overhead” and “zero‑cost abstractions” are repeated constantly in the C++ and Rust communities. They appear in conference talks, Reddit threads, blog posts, and even standard‑committee discussions. But these slogans are not engineering concepts. They are marketing language — and worse, they are often used to shut down nuanced, evidence‑based discussion.
In this chapter, we examine why these slogans are meaningless in practice, why they are routinely misused, and why real‑world performance depends on binary size, memory hierarchy, platform constraints, and economics — not on slogans.
1. The slogan as propaganda
In many online communities (r/cpp, r/rust, etc.), the phrase “zero‑overhead” is used as a rhetorical weapon. Instead of engaging with trade‑offs, people simply assert:
“It’s zero‑overhead, so your argument is invalid.”
This is not engineering. It is propaganda. It prevents discussion about:
- binary size
- instruction cache pressure
- relocation cost
- optimizer complexity
- debuggability
- portability
- economic cost
None of these are “zero.” None of these can be optimized away.
2. Exception handling is not zero‑overhead
C++ exception handling is often marketed as “zero‑overhead” because the happy path contains no explicit checks. But this ignores the real costs:
- larger binary size
- unwind tables and metadata
- more relocation entries
- reduced optimization opportunities
- worse icache locality
For applications where crashing is acceptable (which is
most modern apps), std::abort() is strictly cheaper.
Linux overcommit kills processes. Android and iOS kill apps without permission. Users do not care. They keep buying phones.
So the claim that EH is “zero‑overhead” is simply false.
See Raymond Chen’s article: “Zero-cost exceptions aren’t actually zero cost” .
3. Lambdas are not zero‑overhead
Lambdas duplicate code. Even if two lambdas contain identical bodies, they generate separate instantiations. This increases:
- binary size
- instruction cache pressure
- relocation cost
Larger binaries are slower to load, slower to map, and harder for the optimizer to reason about. None of this is “zero‑overhead.”
4. span and string_view are not zero‑overhead on Windows x64
A common claim is that std::span and std::string_view
are “zero‑overhead” abstractions. This is not true on Windows x86‑64, and the
reason is very concrete: the Windows x64 calling convention only passes
arguments of size 1, 2, 4, or 8 bytes in registers.
Both std::span and std::string_view are 16‑byte
aggregates (a pointer plus a size) on 64‑bit platforms. On Windows x64, such
16‑byte types do not qualify for register passing and are
therefore always passed by memory. This is purely an ABI
rule, not an STL or MSVC bug.
On 32‑bit (i686) and Windows on ARM, and on SysV x86‑64 (Linux, BSD, macOS),
16‑byte aggregates can be passed in registers, so the same
span/string_view code has different calling‑convention
costs across platforms. The Godbolt examples demonstrate this difference
clearly for 64‑bit Windows vs 32‑bit and SysV ABIs.
The key point is that “zero‑overhead” is not a universal property of an abstraction; it depends on the ABI. An abstraction that looks “zero‑overhead” on SysV can be measurably more expensive on Windows x64. Platform rules win over slogans.
5. Instruction ordering and optimizer complexity
Even changing the order of instructions can affect performance. The optimizer must reason about dependencies, aliasing, and scheduling.
More abstraction → more IR → more complexity → fewer optimizations. This is overhead. It is not zero.
6. C++ is used for portability, not performance
Many people claim C++ is used because it is “fast.” In reality, C++ is used because it is:
- portable
- stable
- supported everywhere
- compatible with existing code
Performance is often secondary. In many cases, it is irrelevant.
We will discuss this more in the chapter on Freestanding and Progressive Web Apps, and how mobile app sandboxing (Android, iOS, UWP) makes native apps slower to start, slower to update, and harder to distribute.
7. PWAs can outperform native apps
Consider a simple media player. A PWA can be:
- smaller (under 100 KB)
- faster to start (browser already running)
- cross‑platform by default
- more secure (browser sandbox)
- cheaper to update
Meanwhile, VLC’s installer is over 100 MB. SMPlayer is similar. Updates are expensive. Startup is slower because the entire application must be loaded from disk.
My PWA Player is a concrete demonstration of this. The player itself is under 100 KB, while the browser’s media engine — written in highly optimized C/C++/assembly — is already loaded in memory and shared across processes. The PWA does not re‑implement a media engine; it simply uses the one the browser already provides.
This architecture allows a lightweight PWA to outperform heavyweight native apps in startup time, update cost, and distribution convenience. It directly contradicts the simplistic “C++ is always faster” narrative.
Try it here: https://pwa-player.pages.dev/
8. Economic cost is real overhead
Adding features like exception handling consumes:
- committee time
- compiler engineering resources
- maintenance cost
- testing cost
These resources could have been spent on:
- better optimizations
- better tooling
- better diagnostics
- better portability
Economic cost is overhead. It affects real‑world performance indirectly but significantly.
See Chandler Carruth’s CppCon 2019 talk:
Key takeaways
- “Zero‑overhead” and “zero‑cost” are slogans, not engineering terms.
- They are often used to shut down discussion rather than encourage it.
- Exception handling, lambdas, span, and string_view all have real costs.
- Binary size, icache pressure, and relocation cost matter.
- Platform differences matter; nothing is universally zero‑overhead.
- C++ is used for portability far more than for performance.
- PWAs can outperform native apps because the browser is already running.
- Economic cost is overhead; committee time is not free.
- There are no zero‑cost abstractions — only trade‑offs.