Chapter 07

Indirection Is a Tax

In Chapter 06, we saw that the Stack is fast. You access variables directly.

But what if the data you need is too big for the stack? Or if its size changes (like a list of users)? You have to put it somewhere else—in the Heap—and keep a map to find it.

This map is called a Pointer.

The Treasure Hunt

Pointers are powerful, but they come with a hidden tax: Indirection.

Direct Access: "Give me the apple in your hand." (1 Operation)
Pointer Access: "Give me the paper in your hand. Read the location. Go to that location. Give me the apple there." (2 Operations + Latency).

Every time you follow a pointer, you are asking the CPU to pause its incredibly fast math and wait for the incredibly slow memory bus. Pointer chasing is a treasure hunt where the map is locked in another chest.

Physics Lens: Latency ↑↑ (Double Fetch) | Throughput ↓ (Stalled) | Energy ↑ (Bus Traffic) | Waste ↑ (Cache Miss)
Experiment: Compare accessing a Value (Register) vs a Pointer (RAM). Watch the "Cycles" counter. Following the pointer doubles the cost.

Cache Misses

The problem is worse than just "double the work." The CPU tries to guess what memory you need next (Caching). Pointers are notoriously hard to guess because they can point anywhere.

If the pointer points to a random location, the CPU suffers a Cache Miss. It has to go all the way to main RAM, which takes ~300 clock cycles. This is an eternity. A modern CPU can do 1,000 additions in the time it takes to fetch one pointer miss.

Before memory is accessed, the address must be translated from Virtual to Physical. If this translation is not cached, the CPU must walk page tables. This is called a TLB Miss. It is often slower than a cache miss.

Hypotheses
Why are Linked Lists slow?

Because every node is a pointer. To find the 5th element, you must fetch Node 1, wait, read Node 2's address, fetch Node 2, wait, read Node 3... It is a serialized chain of Cache Misses. An Array, by contrast, gives you the address of the 5th element instantly (Base + 5 * Size).

Why does Java/Python use pointers everywhere?

Convenience. In Java, every Object is a pointer (Reference). This makes memory management easy (you don't allocate manually), but it means almost every interaction involves indirection. This is why high-performance game engines often use C++ or Rust to control memory layout directly.

What is a Null Pointer Exception?

It is when you try to follow a map that says "Destination: 0". Address 0 is typically reserved/protected by the OS to catch exactly this error. The CPU tries to access it, the hardware screams, and the OS kills your process.

What programmers usually get wrong here

Assuming memory access is O(1). Theoretically it is, but physically it varies by 100x depending on whether you hit L1 cache (1ns) or Main RAM (100ns). Pointer chasing guarantees the bad case.

This works — until we scale it. Pointers are convenient, but they fragment memory until the CPU spends more time waiting than working.