Trilha 02 · Como funciona

Memória e armazenamento

Memória rápida é cara. Armazenamento barato é lento. A hierarquia de memória equilibra custo, velocidade e capacidade.

① Intuição

A mesa de trabalho e o arquivo

Imagine que você está estudando: os livros que estão na sua mesa (RAM) você acessa em segundos. Os que estão no armário (SSD) levam um minuto para pegar. Os que estão em depósito (fita magnética) levam horas. Por isso você mantém na mesa só o que está usando agora.

A CPU é ainda mais extrema: ela prefere dados que estão a 0,3 ns de distância (registrador) e sofre esperando 100 ns pela RAM — que para nós parece instantâneo, mas para uma CPU é uma eternidade de 300 ciclos de clock em espera.

Localidade: programas tendem a acessar as mesmas posições de memória repetidamente (localidade temporal) e posições próximas entre si (localidade espacial). O cache explora exatamente isso.
② Visualização interativa

Leia e escreva na memória

Clique em uma célula para "lê-la" (azul). Use o formulário para escrever um valor num endereço (verde). Observe a hierarquia de velocidades abaixo da grade.

MEMÓRIA RAM — 16 ENDEREÇOS (clique para ler)
00
0
01
0
02
0
03
0
04
0
05
0
06
0
07
0
08
0
09
0
0A
0
0B
0
0C
0
0D
0
0E
0
0F
0
HIERARQUIA DE VELOCIDADE DE ACESSO
Registrador
~0,3 ns
Cache L1
~1 ns
Cache L3
~20 ns
RAM
~100 ns
SSD NVMe
~0,1 ms
HDD
~10 ms

A escala é logarítmica — HDD é 33 milhões de vezes mais lento que um registrador.

③ Explicação técnica

A hierarquia completa

Por que o cache faz tanta diferença

# Sem cache: toda leitura vai à RAM (100 ns)
para i em 0..999:
    soma += array[i]   # 1000 × 100 ns = 100 µs

# Com cache: após a primeira leitura, os dados ficam no L1 (1 ns)
para i em 0..999:
    soma += array[i]   # ~1 ns após o cache warm-up = 1 µs (100× mais rápido!)

Política de substituição: LRU

Quando o cache enche e um novo dado precisa entrar, qual dado expulsar? A política LRU (Least Recently Used) expulsa o que foi acessado há mais tempo:

# Cache LRU simples (capacidade = 3)
cache = []  # mais recente na frente

função acessar(página):
    se página em cache:
        cache.mover_para_frente(página)   # hit!
    senão:
        se len(cache) == capacidade:
            cache.remover_último()         # miss: evict LRU
        cache.inserir_frente(página)
Memória virtual: quando a RAM enche, o SO move páginas para o disco (swap) e "finge" que há mais RAM. Isso funciona, mas ler swap do disco é 1.000× mais lento — daí aquela lentidão quando o computador "trava" com muitos programas abertos.
④ Projeto para programar

Implemente uma cache LRU

Mini projeto: implemente a política LRU com um dicionário e uma fila (deque em Python). A função get(chave) retorna o valor ou None se não estiver no cache. A função put(chave, valor) insere e evicta o LRU se necessário.

Projeto principal: instrumente sua implementação para medir a taxa de acertos (hit rate) com diferentes tamanhos de cache e sequências de acesso. Compare LRU com FIFO (expulsa o mais antigo inserido).

Desafio extra: implemente LRU com complexidade O(1) para ambas as operações usando um hash map + lista duplamente encadeada (a solução canônica da entrevista técnica).

⑤ Exercícios rápidos

Teste sua intuição

Por que existe uma hierarquia de memória em vez de uma só?
Qual memória é a mais rápida desta lista?
O que acontece quando a RAM está cheia e você abre mais um programa?
⑥ Aplicações no mundo real

Onde você encontra isso

🎮

Loading screens

Quando um jogo carrega, está copiando texturas, modelos e sons do SSD para a RAM para acessar rapidamente.

🌐

Cache de navegador

O browser salva HTML, CSS e imagens no disco para não baixar novamente — é uma cache de armazenamento, mesma ideia.

🗑️

Garbage collection

Linguagens como Java e Python gerenciam automaticamente a RAM, liberando memória de objetos não usados.

📊

Bancos de dados

PostgreSQL e MySQL mantêm um buffer pool (cache em RAM) das páginas de disco mais acessadas para queries rápidas.

← Anterior: A CPU Próxima: Sistema operacional →