5.4.6Memory Hierarchy & Caches

Write-through vs write-back

2,637 words12 min readdifficulty · medium6 backlinks

The Write Problem

When a CPU performs a store instruction to an address that's cached, we must decide when to update main memory. Both the cache and memory hold copies of the data—they can become inconsistent.

Why this matters: Reads are easy (cache hit = fast, cache miss = fetch from memory). But writes create a dirty state where the cache holds newer data than memory.


Write-Through Policy

How It Works

  1. CPU issues STORE instruction
  2. Cache updates its line (if hit)
  3. Simultaneously, the store is forwarded to memory
  4. Write completes only when memory acknowledges

Derivation of write time: Twrite-through=Tcache-write+Tmemory-writeT_{\text{write-through}} = T_{\text{cache-write}} + T_{\text{memory-write}}

Since Tmemory-writeTcache-writeT_{\text{memory-write}} \gg T_{\text{cache-write}} (memory ~100 ns, cache ~1 ns), the memory access dominates: Twrite-throughTmemory-writeT_{\text{write-through}} \approx T_{\text{memory-write}}

Why this step? The cache write is so fast compared to memory that it becomes negligible in the total time.

Write Buffer Optimization

To hide memory latency, modern write-through caches use a write buffer:

Derivation:

  • CPU writes to cache + buffer (1-2 ns)
  • Buffer drains to memory asynchronously
  • CPU continues if buffer not full

Effective write time: Teffective=Tcache+Tbuffer-insertT_{\text{effective}} = T_{\text{cache}} + T_{\text{buffer-insert}}

The buffer can absorb N writes before stalling (typical N=4-8). If writes arrive faster than buffer drains: Stall occurs whenRwrite>NTmemory-write\text{Stall occurs when} \quad R_{\text{write}} > \frac{N}{T_{\text{memory-write}}}

Why this step? The buffer decouples CPU speed from memory speed, but only up to its depth.


Write-Back Policy

How It Works

  1. CPU issues STORE instruction
  2. Cache updates its line and sets ==dirty bit = 1==
  3. Write completes immediately (no memory access)
  4. On eviction: If dirty bit = 1, write entire line to memory; else discard

Derivation of write time: Twrite-back=Tcache-write(assuming hit)T_{\text{write-back}} = T_{\text{cache-write}} \quad (\text{assuming hit})

Since cache write ~1 ns and memory write ~100 ns: Speedup=Twrite-throughTwrite-back=1001=100×\text{Speedup} = \frac{T_{\text{write-through}}}{T_{\text{write-back}}} = \frac{100}{1} = 100\times

Why this step? We've eliminated memory writes from the critical path by deferring them.

The Eviction Cost

When a dirty line is evicted (e.g., due to conflict miss), we must:

  1. Write dirty line to memory (1 cache line = 64 bytes typically)
  2. Then fetch the new line

Tmiss-with-dirtyevict=Twriteback-old+Tfetch-new=2×Tmemory-accessT_{\text{miss-with-dirtyevict}} = T_{\text{writeback-old}} + T_{\text{fetch-new}} = 2 \times T_{\text{memory-access}}

Why this step? We pay double memory latency: one write, one read. But this only happens on misses with dirty evictions.


Comparative Analysis

Aspect Write-Through Write-Back
Write Latency High (~100 ns) Low (~1 ns)
Memory Traffic Every write Only on evictions
Consistency Always synchronized Delayed (dirty data)
Read Miss Penalty TmemoryT_{\text{memory}} 2×Tmemory2 \times T_{\text{memory}} (if dirty)
Complexity Simple Requires dirty bit, writeback logic
Bus Utilization High Low
Multi-core Coherence Easier (memory up-to-date) Harder (need cache-to-cache transfers)

Derivation of bus utilization:

Write-through: Every write uses the bus. Bus WritesWT=Store Instructions\text{Bus Writes}_{\text{WT}} = \text{Store Instructions}

Write-back: Only evictions use the bus. Bus WritesWB=Store Instructions×Miss Rate×Pdirty\text{Bus Writes}_{\text{WB}} = \text{Store Instructions} \times \text{Miss Rate} \times P_{\text{dirty}}

Typical values: Miss Rate = 5%, PdirtyP_{\text{dirty}} = 50% Bus WritesWBBus WritesWT=0.05×0.5=0.025=140\frac{\text{Bus Writes}_{\text{WB}}}{\text{Bus Writes}_{\text{WT}}} = 0.05 \times 0.5 = 0.025 = \frac{1}{40}

Why this step? Write-back reduces memory traffic by ~40× for workloads with good locality.


Common Mistakes


Cache Write Policies Decision Tree

Write occurs
    │
    ├─ Cache Hit?
    │   ├─ Write-Through: Update cache + memory (100 ns)
    │   └─ Write-Back: Update cache + set dirty (1 ns)
    │
    └─ Cache Miss?
        ├─ Write-Allocate (modern): Fetch line, then write
        │   ├─ Write-Through: Fetch + write cache + write memory
        │   └─ Write-Back: Fetch + write cache + set dirty
        │
        └─ No-Write-Allocate (rare): Write directly to memory

Advanced Considerations

Write-Through + Write-Back Hybrid

Some systems use selective write policies:

  • Frequently accessed data (stack, heap): write-back
  • I/O regions, memory-mapped devices: write-through

Why this step? I/O devices may expect writes to be immediately visible. Write-through ensures this without complex coherence protocols.

Multi-Level Caches

In most modern processors, all cache levels (L1, L2, L3) use write-back to minimize traffic between levels and to memory. A write to L1 updates only L1 and sets its dirty bit; on L1 eviction the dirty line is written back to L2, and on L2 eviction to memory (and so on).

L1writeback on evictL2writeback on evictMemoryL1 \xrightarrow{\text{writeback on evict}} L2 \xrightarrow{\text{writeback on evict}} \text{Memory}

Why this step? Write-back at every level keeps the fast L1→L2 and slow L2→Memory paths off the critical write path. A few designs use a write-through L1 backed by a write-back L2 (simplifying L1 coherence and error recovery), but this is the exception rather than the rule—write-back at all levels is the common modern choice.


Recall Feynman: Explain to a 12-year-old

Imagine you're taking notes in class. You have a small notepad (cache) and a big notebook (memory).

Write-through is like copying every single thing the teacher says into both your notepad AND your big notebook at the same time. It takes longer because you're writing twice, but your big notebook is always up-to-date. If your notepad gets lost, no problem—everything's in the big notebook.

Write-back is like scribbling quick notes on your notepad during class (super fast!), and only copying them to your big notebook at the end of day. Much faster during class, but if you lose your notepad before copying, you've lost today's notes! Also, if someone looks at your big notebook during the day, they won't see your latest notes yet.

The "dirty bit" is like putting a star⭐ on notepad pages that haven't been copied yet, so you remember which pages need copying later.


Connections

  • 5.4.01-CacheFundamentals - Understand cache hits/misses first
  • 5.4.05-Cache-ReplacementPolicies - Eviction triggers writebacks
  • 5.4.07-Cache-Coherence - Write policies affect multi-core coherence
  • 5.4.08-Write-Allocate-vs-No-Write-Allocate - What happens on write misses
  • 6.2.03-Memory-ConsistencyModels - Write visibility in parallel systems
  • 5.3.02-DRAM-Architecture - Why memory writes are slow

#flashcards/hardware

Write-through cache policy :: Every write updates both cache and memory immediately; always synchronized but slower (~100 ns per write)

Write-back cache policy
Writes update only cache with dirty bit set; memory updated on eviction; faster (~1 ns) but delayed consistency
What is the dirty bit?
A per-line flag indicating the cache line has been modified and differs from memory; signals writeback needed on eviction
Write-through speedup with write buffer
Decouples CPU from memory speed by queuing writes; effective if buffer depth ≥ write burst length; stalls if buffer fills
Write-back memory traffic reduction
Reduces writes by ~40× for workloads with locality; only evictions write to memory, not every store instruction
Write miss in write-back cache (write-allocate)
Must fetch line from memory first (~T_memory), then write to cache, plus writeback if evicted line was dirty; costs ~100–200 ns even in write-back
When does write-through win?
Write-once patterns with no temporal locality; streaming writes where write-back offers no amortization; I/O regions requiring immediate visibility
Eviction cost in write-back
Dirty line eviction costs 2× memory latency (writeback old + fetch new); amortized over many writes to same line
Why dirty bit per line, not byte?
Memory writes are line-granular (64B bursts); per-byte tracking too expensive in hardware; entire line written back if any byte dirty
Do modern L1 caches use write-through?
Usually no—most modern processors use write-back at all cache levels (L1, L2, L3); write-through L1 is the exception, not the rule

Concept Map

choice A

choice B

guarantees

cost

mitigated by

stalls when

updates

creates

risk

benefit

core tension

Write problem: when to update memory

Write-through

Write-back

Cache-memory consistency

Slow: memory latency dominates

Write buffer depth N

Write rate exceeds drain rate

Only cache first

Dirty state

Memory inconsistent

Fast writes

Consistency vs speed

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho beta, yahaan core dilemma ye hai ki jab CPU kisi data ko cache mein write karta hai, tab main memory ko kab update karein? Kyunki cache aur memory dono paas same data ki copy hoti hai, agar hum sirf cache update karein toh dono inconsistent ho jaate hain. Iske do solutions hain: write-through matlab har write ko turant memory tak bhej do - safe hai kyunki cache aur memory hamesha synchronized rehte hain, lekin slow hai kyunki memory ~100ns leti hai jabki cache sirf ~1ns. Doosra hai write-back jahan tum sirf cache mein likhte ho aur ek "dirty bit" set kar dete ho, aur memory ko baad mein update karte ho jab woh cache line evict hoti hai - ye bahut fast hai (almost 100x speedup!) lekin thoda risky kyunki kuch time ke liye memory purana data rakhti hai.

Ise samajhne ke liye apne notes ka example socho - write-through matlab har thought ke baad apni master notebook update karna (safe par time-consuming), aur write-back matlab pehle rough draft mein likhna aur baad mein clean copy karna (fast par agar draft kho gaya toh problem). Write-through ki speed thodi improve karne ke liye ek write buffer use hota hai jo writes ko temporarily hold karke asynchronously memory mein daalta hai, taaki CPU ruke nahi - par jab buffer full ho jaaye toh stall ho jaata hai. Write-back mein twist ye hai ki jab dirty line evict hoti hai, tab do kaam karne padte hain: pehle purani dirty line memory mein likhna, phir nayi line fetch karna - matlab ek miss do memory accesses ka cost le sakti hai.

Ye topic isliye important hai kyunki real-world processors mein ye trade-off directly performance ko affect karta hai. Write-heavy workloads mein (jahan bahut zyada writes ho rahe hain) write-back kaafi faster hota hai kyunki wahi memory location baar-baar update ho sakti hai bina memory ko touch kiye. Isliye modern CPUs mostly write-back use karte hain performance ke liye. System design, OS, aur computer architecture interviews mein ye concept bahut aata hai, aur agar tum caching, consistency ya multi-core systems samajhna chahte ho toh ye foundation banta hai. Toh dono policies ka trade-off - consistency vs speed - yaad rakho, yahi asli takeaway hai.

Go deeper — visual, from zero

Test yourself — Memory Hierarchy & Caches

Connections