Pode parecer trivial, mas a maior parte dos devs que não viveu o “inferno bom” dos anos 2000 (hardware limitado, IO lento, RAM cara) não entende um ponto básico: hoje a gente tem abundância de capacidade, mas continua preso nas mesmas limitações de latência — só que agora com volume acumulado e complexidade absurda.

E aí nasce a mentira moderna: “CPU tá fraca”. Não tá. O gargalo real, na maioria dos sistemas, é outro.

O grande vilão não é processamento: é memória + movimento de dados

CPU/GPU moderna cospe milhões/bilhões de operações por segundo. Só que pra operar, ela precisa de dados. E o dado tem que viajar:

  • do SSD pro RAM

  • do RAM pro cache

  • do cache pro registrador

  • do registrador pra ALU

O custo não é fazer a+b. O custo é trazer a e b até o lugar certo, na hora certa, sem destruir tudo no caminho.

A indústria ficou viciada em paralelismo porque “parece” solução. Só que paralelismo sem controle de memória vira: mais contenção, mais cache miss, mais cópia, mais lock, mais GC, mais aleatoriedade.

“Mas meu servidor é forte” — e daí? Sua RAM não é mágica

RAM tem uma característica que dev ignora: acesso é caro quando vira bagunça.

E tem outro detalhe que quase ninguém encara de frente: do ponto de vista de performance, as operações não custam igual:

  • leitura sequencial e previsível: barata (quando acerta cache, quando tem locality)

  • escrita espalhada: mais cara

  • update em estrutura cheia de ponteiro: pior

  • delete + realocação + GC: pior ainda

Não é que “memória é ruim pra atualizar” por definição teórica. É que o ecossistema inteiro (cache, prefetch, branch predictor, TLB, alocador, GC) foi otimizado pra fluxo previsível. Quando seu programa vira um carnaval de ponteiros e objetos espalhados, você perde.

Stack vs Heap: aqui nasce metade da sua dor

Se o dado é simples, curto, escopo bem definido, o compilador empilha no stack. Isso é vida:

  • rápido

  • previsível

  • cache-friendly

  • sem GC

Agora entra o mundo moderno OOP de “tudo é objeto”. Aí você cai no heap:

  • alocação custa

  • desalocação custa

  • fragmentação custa

  • GC custa (mesmo quando “quase não pausa”)

E o pior: objeto orientado a herança e polimorfismo espalha dados. Você não tem uma estrutura compacta: você tem uma árvore de ponteiros. Isso mata locality e transforma CPU em “motor de busca” procurando dado na memória.

OOP é ótimo pra humano. Pra máquina, em escala, é imposto.

“Mas Java tem threading foda” — tem, mas o mundo real ainda sangra

Sim: a JVM é uma das melhores engenharias já feitas pra concorrência, JIT e runtime. E virtual threads deixam muita coisa mais fácil.

Só que “facilidade” não elimina física. Se seu design cria:

  • milhões de objetos por segundo

  • estruturas com ponteiro pra todo lado

  • cópia pra todo lado (buffers, strings, JSON)

  • sincronização demais

…não tem runtime que faça milagre. Vai rodar “ok” até o dia que não roda. E aí você chama isso de “mistério de produção”.

Compilador, linker e o preço real da abstração

Aqui entra um ponto e é ouro: o custo de compor o sistema.

C++ separa header por um motivo histórico e prático: dá pra entender “o contrato” antes de linkar tudo. Muita gente trata isso como “velharia”, mas é o tipo de velharia que existe porque resolveu problemas reais.

E sim: quem mexe com LLVM sabe — linking é caro, IR explode, dependência vira bola de neve. Conforme você aumenta cobertura de libs e testes, aparece o que ninguém quer ver:

  • cache estoura

  • build vira paciência

  • typechecker vira gargalo

  • codegen vira gargalo

Isso é o mesmo tema, só que no seu toolchain: movimento de dados e complexidade de composição.

O ponto central: imutabilidade não é filosofia, é estratégia de performance

Se update e delete são caros, a pergunta correta é:

como eu evito update e delete?
como eu evito cópia?
como eu mantenho dado compacto e previsível?

Imutabilidade aqui não é papo funcional bonitinho. É engenharia:

  • menos escrita espalhada

  • menos invalidação de cache

  • menos sincronização

  • menos bug de concorrência

  • menos trabalho pro GC

  • mais previsibilidade

Rust virou referência porque empurrou isso pro compilador: ownership/borrowing força disciplina e reduz lixo. Não é “religião anti-OOP”, é foco em eficiência.

Sim, fica mais verboso. Sim, dói no começo. Mas é o tipo de dor que te poupa o inferno depois.

A mentira do mercado: “é só escalar”

“Compra mais servidor”, “escala horizontal”, “separa em microserviço”.

Isso é o novo “reinicia o modem”.

Escalar é ferramenta. Quando vira muleta, você só fez isso:

  • jogou o custo pra infra

  • jogou o custo pra rede

  • multiplicou latência

  • multiplicou complexidade

  • multiplicou pontos de falha

O resultado é o padrão atual: empresa queimando dinheiro e chamando de arquitetura.

E sim: AWS lucra com incompetência média. Não é teoria conspiratória. É incentivo econômico básico: abstração mal usada vira fatura.

E o que isso tem a ver com você?

Tudo.

O mercado tá indo pra dois movimentos ao mesmo tempo:

  1. reduzir custo de dev com IA

  2. reduzir custo de infra (porque hardware tá mais caro e demanda tá insana)

RAM e SSD ficaram mais caros em vários ciclos recentes e a pressão de datacenter/IA só amplifica isso. Se a tua aplicação depende de “comprar mais RAM” pra existir, você tá em risco.

E aí entra o lado feio: teu chefe não quer filosofia. Ele quer reduzir conta. Se você não entende o básico de memória, vai continuar entregando software que só funciona com escala e reza.

Aí quando vier a cobrança, você já sabe: o cara que vira “dispensável” é o que não consegue explicar o gargalo com precisão e só responde com buzzword.

O caminho prático

Se você quer sair do buraco, começa por aqui:

  • pare de criar objeto a rodo (principalmente em hot path)

  • dado compacto > objeto bonito

  • prefira estruturas contíguas (array, slice, struct-of-arrays quando faz sentido)

  • reduza alocação no heap

  • evite cópia (string, JSON, buffers)

  • cache e locality são rei

  • meça de verdade: p95/p99, alocação por request, GC time, cache miss (quando possível)

Performance não é “micro-otimização”. Performance é arquitetura que respeita a física da memória.

E quem entender isso agora, vai surfar a era da IA. Quem não entender, vai continuar sendo “dev de framework” — e vai tomar a pancada quando a empresa decidir cortar custo sem dó.