跳到正文
原文
Google AI:DEV 作者专属(RSS)· Matheus de Camargo Marques·· 7 小时前AI 评分24

Elixir Enchiridium 第二卷:机器(第 61-100 章)

Elixir Enchiridium — Tomo II: A Máquina parte 3

AI 导读

这是一部基于 Elixir 真实技术事实的讽刺奇幻系列第二卷,涵盖第 61 至 100 章,每章末尾揭示传说背后的真实技术细节。

正文

AVISO: esta série é uma fantasia satírica baseada em fatos reais sobre Elixir. Nada aqui deve ser levado ao pé da letra. Ao final de cada capítulo, os fatos por trás da lenda são revelados. Tags: #satire #humor #elixir #enchiridium


Elixir Enchiridium — Tomo II: A Máquina

Capítulos 61 a 100


Capítulo 61 — O Nó: A Ilha que se Conecta a Tudo

A lenda diz que cada instância da BEAM é uma ilha. Uma ilha flutuante no oceano da rede. Ela tem seu próprio nome, seus próprios processos, sua própria memória. Mas, quando duas ilhas se encontram, elas se tornam um arquipélago. Compartilham tudo. Processos de uma podem falar com processos de outra. E o melhor: o programador nem percebe.

A verdade é que um nó Erlang (ou nó Elixir) é uma instância da máquina virtual. Cada nó tem um nome único (como :app@192.168.1.1). Quando dois nós se conectam, eles formam um cluster. Processos podem ser enviados de um nó para outro. Mensagens podem ser enviadas para PIDs em nós remotos. E a distribuição é transparente: send(pid, msg) funciona igual, seja o processo local ou remoto.

A lenda diz que, na primeira vez que um programador viu dois nós se conectando, ele perguntou: "Como eles se encontraram?" O instrutor respondeu: "Pergunte ao EPMD." O programador perguntou: "O que é EPMD?" O instrutor respondeu: "O cartório dos nós."

O fato por trás da lenda: Um nó Erlang é uma instância da máquina virtual com um nome único. Quando dois nós se conectam, formam um cluster. A distribuição é embutida na BEAM e é transparente para o programador. O EPMD (Erlang Port Mapper Daemon) é o serviço que mapeia nomes de nós para portas.

Gancho: EPMD é o cartório. Mas há uma ferramenta que organiza o arquipélago: o Libcluster.


Capítulo 62 — Libcluster: O Feitiço que Junta os Nós (Parte 2)

A lenda diz que, para formar um cluster, você precisa de magia. Você roda libcluster e, de repente, todos os nós se encontram, se cumprimentam e começam a trabalhar juntos. Se um nó morre, os outros sentem falta. Se um nó nasce, os outros dão boas-vindas. O Libcluster é o mestre de cerimônias do arquipélago.

A verdade é que o Libcluster fornece um mecanismo para formar automaticamente clusters de nós Erlang, com adesão estática ou dinâmica. Ele suporta várias estratégias: EPMD, Kubernetes, Gossip, DNS, Rancher, e outras. A estratégia Cluster.Strategy.Gossip usa o protocolo multicast gossip para formar um cluster dinamicamente. A estratégia Cluster.Strategy.Kubernetes usa a API do Kubernetes para consultar endpoints.

A lenda diz que, na primeira vez que um programador usou Libcluster, ele perguntou: "Como isso funciona?" O instrutor respondeu: "Magia." O programador perguntou: "Mas como?" O instrutor respondeu: "Magia com estratégia."

O fato por trás da lenda: Libcluster fornece formação automática de clusters de nós Erlang, com adesão estática ou dinâmica. Ele suporta várias estratégias: EPMD, Kubernetes, Gossip, DNS, Rancher, e outras.

Gancho: Libcluster conecta nós. Mas há uma coisa que explica os limites: o Teorema CAP.


Capítulo 63 — CAP: O Teorema que a BEAM Ignora (ou Não)

A lenda diz que, quando os aliens criaram a BEAM, eles leram o Teorema CAP e disseram: "Vamos escolher AP." E assim fizeram. A maioria das bibliotecas distribuídas do Elixir fica do lado AP do Teorema CAP: elas preferem manter o sistema disponível mesmo diante de partições de rede, tolerando inconsistências temporárias.

A verdade é que a maioria das bibliotecas distribuídas do Elixir (Phoenix Pub/Sub, Horde, Swarm, Delta CRDTs) fica do lado AP do Teorema CAP. Elas preferem disponibilidade a consistência estrita. No entanto, existem bibliotecas como o Paxtor que escolhem o lado CP (Consistência e Tolerância a Partição), sacrificando disponibilidade quando necessário para preservar consistência forte.

A lenda diz que, quando um programador perguntou "Qual lado é melhor?", o instrutor respondeu: "Depende do que você não pode perder." O programador perguntou: "E se eu não puder perder nada?" O instrutor respondeu: "Aí você precisa de consenso."

O fato por trás da lenda: A maioria das bibliotecas distribuídas do Elixir fica do lado AP do Teorema CAP (Phoenix Pub/Sub, Horde, Swarm, Delta CRDTs). O Paxtor é uma biblioteca CP que usa Paxos para garantir consistência forte.

Gancho: CAP explica os limites. Mas há uma coisa que a BEAM faz melhor que qualquer outra: tolerância a falhas.


Capítulo 64 — Tolerância a Falhas: A Filosofia que Virou Benchmark (Parte 2)

A lenda diz que, num benchmark acadêmico, o Elixir foi comparado a outras linguagens concorrentes sob condições de falha. O resultado? "Elixir atingiu o maior throughput e a menor variabilidade de throughput sob condições de falha". Os aliens aplaudiram. Os humanos tomaram café.

A verdade é que a tolerância a falhas da BEAM é um dos seus pontos mais fortes. Processos isolados, supervisores, árvores de supervisão, "let it crash" — tudo isso faz com que sistemas BEAM se recuperem de falhas de forma quase automática. Um benchmark acadêmico mostrou que Elixir atinge o maior throughput e a menor variabilidade sob condições de falha, comparado a outras linguagens concorrentes.

O fato por trás da lenda: A tolerância a falhas da BEAM é um dos seus pontos mais fortes. Processos isolados, supervisores, árvores de supervisão, "let it crash" — tudo isso faz com que sistemas BEAM se recuperem de falhas de forma quase automática.

Gancho: Tolerância a falhas é a base. Mas há uma coisa que mantém os processos vivos: os supervisores.


Capítulo 65 — Supervisores: As Babás que Nunca Dormem (Parte 2)

A lenda diz que os supervisores são babás que dão mamadeira para processos órfãos. Se um processo morre, a babá chora, pega um novo processo no berçário e coloca no lugar. A estratégia one_for_one significa que ela só troca uma fralda por vez. A rest_for_one é quando ela troca todas as fraldas da fileira. A one_for_all é quando ela surta e reinicia o berçário inteiro.

A verdade é que supervisores são processos que monitoram outros processos (chamados de processos filhos) e os reiniciam quando falham. Supervisores formam árvores de supervisão que fornecem tolerância a falhas e capacidades de auto-recuperação. O comportamento supervisor é um dos comportamentos padrão do OTP, junto com gen_server, gen_event e gen_fsm.

O fato por trás da lenda: Supervisores monitoram processos filhos e os reiniciam quando falham. Supervisores formam árvores de supervisão que fornecem tolerância a falhas e auto-recuperação. O comportamento supervisor é um dos comportamentos padrão do OTP.

Gancho: Supervisores cuidam. Mas há um processo que serve: o GenServer.


Capítulo 66 — GenServer: O Mordomo que Serve Estado em Bandejas (Parte 2)

A lenda diz que um GenServer é um mordomo chamado Alfred que guarda o estado do seu sistema em uma bandeja de prata. Quando você chama GenServer.call, ele responde "Pois não, senhor" e executa a função. Se você usar GenServer.cast, ele anota o recado e vai fazer depois, sem pressa.

A verdade é que GenServer é um comportamento do OTP para construir servidores genéricos. Ele encapsula estado e concorrência, permitindo que você defina callbacks para lidar com chamadas síncronas e assíncronas. GenServer é um dos blocos de construção fundamentais de aplicações Elixir. O callback code_change/3 é usado para migrar o estado durante hot code upgrades.

O fato por trás da lenda: GenServer é um comportamento do OTP para construir servidores genéricos. Ele encapsula estado e concorrência, com callbacks para chamadas síncronas e assíncronas. O callback code_change/3 é usado para migrar o estado.

Gancho: GenServer serve. Mas há uma coisa que persiste: o Ecto.


Capítulo 67 — Ecto: O Fantasma que Assombra Bancos de Dados (Parte 2)

A lenda diz que Ecto é um fantasma que mora no seu PostgreSQL e escreve queries em latim. Cada Repo.insert é um exorcismo. Se você esquecer de fechar a transação, o fantasma sai do banco e assombra seu servidor.

A verdade é que Ecto é uma biblioteca de persistência para Elixir. Ele fornece uma camada de mapeamento entre o código Elixir e o banco de dados, com suporte a migrações, queries e transações. Ecto é dividido em quatro componentes principais: Ecto.Repo, Ecto.Schema, Ecto.Query e Ecto.Changeset.

O fato por trás da lenda: Ecto é uma biblioteca de persistência para Elixir, com componentes para repositórios, schemas, queries e changesets. Ele fornece mapeamento de dados e queries integradas à linguagem.

Gancho: Ecto persiste. Mas há uma coisa que conecta tudo: o Phoenix.


Capítulo 68 — Phoenix: A Fênix que Nasceu das Cinzas (Parte 2)

A lenda diz que Phoenix é um framework web que invoca uma fênix de verdade. Cada vez que você roda mix phx.server, uma fênix renasce das cinzas no Arizona. Isso consome 3% da energia mundial, mas o hot reload é instantâneo.

A verdade é que Phoenix é um framework web para Elixir, criado por Chris McCord. Ele foi lançado em 2015 e se tornou o framework web padrão para Elixir. Phoenix aproveita a BEAM para fornecer alta performance e concorrência, e o LiveView permite criar aplicações interativas sem JavaScript.

O fato por trás da lenda: Phoenix é um framework web para Elixir, criado por Chris McCord e lançado em 2015. Ele se tornou o framework web padrão para Elixir e inclui o LiveView para aplicações interativas sem JavaScript.

Gancho: Phoenix constrói. Mas há uma coisa que conecta usuários: o LiveView.


Capítulo 69 — LiveView: A Janela para o Multiverso (Parte 2)

A lenda diz que, na primeira vez que alguém rodou uma LiveView, uma janela para outra dimensão se abriu no navegador. O usuário viu o conteúdo em tempo real porque estava literalmente olhando para o multiverso.

A verdade é que Phoenix LiveView permite construir experiências de usuário ricas e em tempo real com HTML renderizado no servidor, sem escrever JavaScript. O servidor gerencia o estado e envia atualizações de UI pela conexão WebSocket. A versão 1.0 foi lançada em dezembro de 2024.

O fato por trás da lenda: Phoenix LiveView permite construir aplicações interativas renderizadas no servidor sem JavaScript. A versão 1.0 foi lançada em dezembro de 2024.

Gancho: LiveView interage. Mas há uma coisa que conecta nós: o Libcluster.


Capítulo 70 — Observer: A Janela para a Alma da BEAM (Parte 2)

A lenda diz que, se você quer ver a alma da BEAM, abra o Observer. Ele mostra todos os processos, todos os nós, toda a memória. Você vê a máquina respirando. Você vê os processos nascendo e morrendo. Você vê a BEAM viva.

A verdade é que o Observer é uma ferramenta gráfica para inspecionar sistemas Erlang/Elixir em execução. Ele mostra informações do sistema, árvores de supervisão de aplicações, informações de processos, tabelas ETS ou Mnesia, e contém um frontend para tracing de Erlang. Ele também inclui o etop (uma ferramenta para apresentar informações sobre processos Erlang) e o crashdump_viewer (uma ferramenta HTML para navegar em crashdumps). O Observer também contém o ttb (Trace Tool Builder).

A lenda diz que, na primeira vez que um programador abriu o Observer, ele perguntou: "O que é isso?" O instrutor respondeu: "A alma da BEAM." O programador ficou olhando por uma hora.

O fato por trás da lenda: Observer é uma ferramenta gráfica para inspecionar sistemas Erlang/Elixir em execução. Ele mostra informações do sistema, árvores de supervisão, informações de processos, tabelas ETS e contém frontend para tracing. Inclui etop e crashdump_viewer.

Gancho: Observer mostra a alma. Mas há uma coisa que nem o Observer consegue mostrar: o futuro.


Capítulo 71 — O Futuro da BEAM: Tipos, IA e a Máquina do Amanhã (Parte 2)

A lenda diz que o futuro da BEAM é tipado, inteligente e distribuído. O v1.20 trouxe inferência de tipos. O Nx trouxe IA. O LiveView trouxe interatividade sem JavaScript. E a BEAM continua rodando, com suas capivaras quânticas girando manivelas.

A verdade é que a BEAM está evoluindo. O Elixir está se tornando gradualmente tipado, com inferência de tipos de todos os construtos no v1.20. O Nx está trazendo ML para a BEAM. O LiveView está redefinindo o desenvolvimento web. E a comunidade continua crescendo. O JIT continua sendo melhorado, com o OTP 26 trazendo otimizações baseadas em tipos que tornaram a codificação Base64 cerca de 4 vezes mais rápida.

O fato por trás da lenda: A BEAM está evoluindo. O Elixir está se tornando gradualmente tipado. O Nx traz ML para a BEAM. O LiveView redefine o desenvolvimento web. A comunidade cresce.

Gancho: O futuro é promissor. Mas antes de terminar este tomo, precisamos falar de uma coisa: o alocador de memória.


Capítulo 72 — erts_alloc: O Alocador que Ninguém Vê (Parte 3)

A lenda diz que erts_alloc tem muitos ajudantes. temp_alloc cuida das alocações temporárias. eheap_alloc cuida dos heaps dos processos. binary_alloc cuida dos binários. ets_alloc cuida das tabelas ETS. sl_alloc cuida das listas de atalhos. fix_alloc cuida dos blocos de tamanho fixo. ll_alloc cuida dos blocos de longa duração. std_alloc cuida do resto. Cada um tem seu trabalho. Cada um faz bem.

A verdade é que erts_alloc fornece uma série de alocadores especializados para diferentes tipos de dados. Os principais são: temp_alloc (alocações temporárias), eheap_alloc (heaps de processos), binary_alloc (binários), ets_alloc (tabelas ETS), sl_alloc (blocos de curta duração), ll_alloc (blocos de longa duração, como código Erlang), fix_alloc (blocos de tamanho fixo), std_alloc (a maioria dos blocos não alocados por outros), driver_alloc (dados de drivers), literal_alloc (termos constantes). A ideia principal é separar blocos de memória usados de forma diferente em áreas distintas, reduzindo a fragmentação.

A lenda diz que, quando um programador perguntou "Qual é o melhor alocador?", o instrutor respondeu: "O que você precisa?" O programador perguntou: "Como assim?" O instrutor respondeu: "Cada um é melhor para uma coisa."

O fato por trás da lenda: erts_alloc fornece alocadores especializados: temp_alloc, eheap_alloc, binary_alloc, ets_alloc, sl_alloc, ll_alloc, fix_alloc, std_alloc, driver_alloc, literal_alloc. A ideia é separar blocos de memória usados de forma diferente para reduzir fragmentação.

Gancho: O alocador trabalha. Mas há uma coisa que ele não pode alocar: tempo.


Capítulo 73 — O Código que a BEAM Executa: BEAM Assembly (Parte 2)

A lenda diz que a BEAM não executa código Erlang. Ela executa BEAM assembly. Quando você compila um módulo Erlang ou Elixir, ele é traduzido para instruções BEAM. Essas instruções operam em registradores. Elas testam condições. Elas saltam. Elas chamam funções. A BEAM executa essas instruções como um intérprete de código threaded.

A verdade é que a BEAM é uma máquina de registradores. Quando você compila código Erlang, ele é traduzido para instruções BEAM como {move, {integer,0}, {x,1}} e {call_only,2,{f,4}}. A BEAM executa essas instruções como um intérprete de código threaded, ou, com o JIT, como código nativo. O JIT do OTP 26 usa informações de tipo geradas pelo compilador para otimizar o código nativo.

A lenda diz que, quando um programador viu o BEAM assembly pela primeira vez, ele perguntou: "Isso é Assembly?" O instrutor respondeu: "É BEAM assembly." O programador perguntou: "Qual a diferença?" O instrutor respondeu: "BEAM assembly é bonito."

O fato por trás da lenda: A BEAM executa instruções BEAM, que são geradas pela compilação de código Erlang ou Elixir. As instruções operam em registradores e são executadas como um intérprete de código threaded ou, com o JIT, como código nativo.

Gancho: A BEAM executa instruções. Mas quem decide quais instruções? O carregador de código.


Capítulo 74 — O Carregador de Código: O Bibliotecário da BEAM (Parte 3)

A lenda diz que o bibliotecário da BEAM tem um ajudante chamado purge. Quando um módulo é carregado pela terceira vez, o purge aparece e remove a versão antiga. Se algum processo ainda estiver usando a versão antiga, o purge o mata. Sem piedade. Sem choro. O bibliotecário não gosta de processos apegados a código antigo.

A verdade é que, quando um módulo é carregado pela terceira vez, o code server remove (purga) o código antigo e quaisquer processos que ainda estejam nele são terminados. Isso é importante para entender porque o hot code swapping tem limitações: você não pode manter infinitas versões de um módulo na memória.

A lenda diz que, quando um programador perguntou "Por que meu processo morreu?", o bibliotecário respondeu: "Porque ele estava usando código antigo." O programador perguntou: "Posso impedir?" O bibliotecário respondeu: "Sim. Não use código antigo."

O fato por trás da lenda: Quando um módulo é carregado pela terceira vez, o code server purga o código antigo e mata os processos que ainda o usam. Isso é uma limitação do hot code swapping.

Gancho: O bibliotecário guarda os módulos. Mas há uma coisa que ele não guarda: o estado dos processos.


Capítulo 75 — O Estado dos Processos: O Que Ninguém Vê (Parte 3)

A lenda diz que, quando um processo é suspenso, seu estado é salvo em uma struct chamada Process. A struct contém tudo: o heap, a stack, a mailbox, os registradores. Quando o processo é retomado, o estado é restaurado. O processo nem percebe que foi suspenso. Ele continua como se nada tivesse acontecido.

A verdade é que o estado de um processo Erlang é mantido em uma struct chamada Process. A BEAM mantém parte do estado em variáveis locais e registradores da CPU, salvando essa parte na struct Process quando o processo é suspenso. Cada processo tem sua própria stack, heap, message queue e PCB.

A lenda diz que, quando um programador perguntou "Onde está o estado?", o instrutor respondeu: "No processo." O programador perguntou: "Posso vê-lo?" O instrutor respondeu: "Só se você for o processo."

O fato por trás da lenda: O estado de um processo Erlang é mantido em uma struct chamada Process. A BEAM mantém parte do estado em variáveis locais e registradores da CPU, salvando essa parte na struct Process quando o processo é suspenso.

Gancho: O estado é invisível. Mas há uma coisa que torna o estado visível: o sys.


Capítulo 76 — OTP 27 e Além: O Futuro do JIT (Parte 2)

A lenda diz que, depois do OTP 26, veio o OTP 27. E o OTP 27 trouxe mais otimizações. O JIT ficou mais esperto. O compilador ficou mais inteligente. As otimizações baseadas em tipos foram estendidas. E a BEAM ficou ainda mais rápida.

A verdade é que o OTP 27 continuou o trabalho do OTP 26. As otimizações baseadas em tipos foram estendidas. O compilador continua produzindo melhores informações de tipo, e o JIT continua aproveitando-as. O OTP 27 trouxe otimizações para record operations e outras áreas. A história das otimizações modernas começou em janeiro de 2018, com a introdução de uma representação intermediária baseada em SSA no compilador. O OTP 24 introduziu o JIT, o OTP 25 introduziu otimizações baseadas em tipos no JIT, e o OTP 26 as melhorou.

A lenda diz que, quando um programador perguntou "Até onde o JIT pode ir?", o instrutor respondeu: "Até onde a BEAM quiser." O programador perguntou: "E onde a BEAM quer?" O instrutor respondeu: "Onde você quiser."

O fato por trás da lenda: O OTP 27 continuou as otimizações baseadas em tipos do OTP 26. A história das otimizações modernas começou em 2018 com SSA, passou pelo JIT no OTP 24, otimizações baseadas em tipos no OTP 25, e melhorias no OTP 26.

Gancho: O JIT é o futuro. Mas há uma coisa que sempre foi o presente: a comunidade.


Capítulo 77 — Ports e NIFs: As Janelas para o Mundo (Parte 2)

A lenda diz que a BEAM não roda sozinha. Ela precisa se comunicar com o mundo exterior. Para isso, ela usa Ports e NIFs. Ports permitem que a BEAM se comunique com programas externos. NIFs permitem que a BEAM execute código nativo.

A verdade é que Ports movem código perigoso para um processo de SO separado, garantindo segurança e isolamento. NIFs (Native Implemented Functions) executam código nativo diretamente na thread do scheduler da BEAM, oferecendo performance máxima mas com risco de travar a máquina virtual inteira. Com Erlang/OTP 20+, existem Dirty NIFs, que executam em um pool de threads dedicado, permitindo cálculos longos sem bloquear o scheduler. Dirty NIFs são classificados como CPU-bound (ERL_NIF_DIRTY_JOB_CPU_BOUND) ou IO-bound (ERL_NIF_DIRTY_JOB_IO_BOUND).

A lenda diz que, quando um programador descobriu os NIFs, ele disse: "Posso escrever código C e rodar na BEAM?" O instrutor respondeu: "Pode. Mas cuidado." O programador perguntou: "Por quê?" O instrutor respondeu: "Porque se o NIF travar, a BEAM inteira trava." O programador ficou em silêncio.

O fato por trás da lenda: Ports movem código para um processo de SO separado. NIFs executam código nativo na thread do scheduler, com performance máxima mas risco de travar a BEAM. Dirty NIFs executam em pool de threads dedicado, classificados como CPU-bound ou IO-bound.

Gancho: Ports e NIFs são as janelas da BEAM. Mas há uma ferramenta que observa tudo: o Observer.


Capítulo 78 — OTP 26 e o JIT: A BEAM Ficou Mais Rápida (Parte 3)

A lenda diz que, em 2023, a Ericsson lançou o OTP 26. A grande novidade era o compilador JIT estendido. A BEAM sempre foi interpretada, mas com o JIT, ela passou a compilar código para linguagem de máquina em tempo de execução. O resultado foi um ganho de performance significativo. O JIT do OTP 26 estendeu as otimizações baseadas em tipos, resultando em menos testes de tipo redundantes e código nativo menor.

A verdade é que o OTP 26 introduziu otimizações estendidas baseadas em tipos no compilador e JIT. No OTP 25, o compilador começou a incluir informações de tipo nos arquivos BEAM gerados, para que o JIT pudesse usá-las ao gerar código. No OTP 26, essas otimizações foram estendidas, resultando em melhorias significativas. As melhorias mais notáveis foram na correspondência e construção de binários usando bit syntax. Combinadas com mudanças no módulo base64, a codificação para Base64 ficou cerca de 4 vezes mais rápida e a decodificação mais de 3 vezes mais rápida.

A lenda diz que, na primeira vez que um programador rodou um benchmark com o OTP 26, ele olhou para o resultado e disse: "Isso está errado." Rodou de novo. O resultado era o mesmo. Ele olhou para o terminal e disse: "A BEAM ficou mais rápida." A BEAM respondeu: "Sempre fui. Agora vocês perceberam."

O fato por trás da lenda: OTP 26 introduziu otimizações estendidas baseadas em tipos no compilador e JIT. As melhorias mais notáveis foram na correspondência e construção de binários usando bit syntax. A codificação para Base64 ficou cerca de 4 vezes mais rápida, e a decodificação mais de 3 vezes mais rápida.

Gancho: O JIT tornou a BEAM mais rápida. Mas há uma coisa que sempre foi rápida: os processos leves.


Capítulo 79 — Hot Code Swapping: A Magia de Trocar o Motor com o Carro Andando (Parte 2)

A lenda diz que, na BEAM, você pode trocar o motor com o carro andando. Você atualiza o código de um sistema em execução sem pará-lo. Sem downtime. Sem reiniciar. O sistema continua rodando enquanto o código é trocado.

A verdade é que o hot code swapping é uma das características mais distintivas da BEAM. Ela permite que o código de um sistema em execução seja atualizado sem pará-lo. Isso é possível porque a BEAM mantém duas versões do código em memória: a antiga e a nova. Quando um processo precisa executar uma função, ele usa a versão mais recente. O OTP fornece o callback code_change/3 para migrar o estado entre versões. Antes de fazer o hot code load de um módulo, é preciso primeiro destruir a versão mais antiga do módulo.

A lenda diz que, na primeira vez que um engenheiro da Ericsson viu o hot code swapping em ação, ele disse: "Isso é impossível." O sistema respondeu: "Não é." E continuou rodando.

O fato por trás da lenda: Hot code swapping é uma das características mais distintivas da BEAM. Ela permite que o código de um sistema em execução seja atualizado sem pará-lo. A BEAM mantém duas versões do código em memória, e o OTP fornece o callback code_change/3 para migrar o estado.

Gancho: Hot code swapping é uma revolução. Mas há uma coisa que nem a BEAM consegue fazer: prever o futuro.


Capítulo 80 — O Scheduler Preemptivo: O Juiz que Nunca Dorme (Parte 2)

A lenda diz que o scheduler da BEAM é um juiz que nunca dorme. Ele olha para cada processo e diz: "Você já rodou o suficiente. Próximo." Os processos obedecem. Se não obedecessem, o scheduler os interromperia.

A verdade é que o scheduler da BEAM usa preempção baseada em reduções. Cada processo recebe uma cota de reduções (cerca de 2000) antes de ser preemptado. Uma redução representa uma unidade de trabalho realizada por um processo. O scheduler mantém o controle das reduções executadas por cada processo, preemptando um processo quando ele atinge um certo número de reduções, permitindo que outro processo rode. O scheduler é projetado para eficiência em multi-core, tipicamente rodando um scheduler por núcleo de CPU.

A lenda diz que o scheduler é justo porque nunca deixou um processo monopolizar a CPU. Nem mesmo o processo que queria calcular o último dígito de Pi.

O fato por trás da lenda: O scheduler da BEAM usa preempção baseada em reduções. Cada processo recebe uma cota de reduções (cerca de 2000) antes de ser preemptado. Uma redução é uma unidade de trabalho. O scheduler roda um por núcleo de CPU.

Gancho: O scheduler distribui reduções. Mas o que é uma redução, exatamente?


Capítulo 81 — Reduções: A Moeda do Tempo na BEAM (Parte 2)

A lenda diz que, na BEAM, o tempo não é medido em segundos. É medido em reduções. Uma redução é a menor unidade de trabalho. Uma chamada de função custa uma redução. Uma operação aritmética custa uma redução. Uma mensagem custa uma redução. Se você tem reduções, você tem tempo. Se não tem, você espera.

A verdade é que o conceito de redução vem do Prolog. Em Prolog, cada passo de execução é chamado de "goal-reduction". A BEAM herdou o conceito e o usa para preempção. Cada processo recebe um orçamento de reduções e, quando ele acaba, o processo é suspenso. A execução na BEAM é estruturada em torno de reduções, que representam unidades de trabalho realizadas por um processo.

A lenda diz que um programador tentou comprar reduções com café. Não funcionou. Mas ele conseguiu um aumento.

O fato por trás da lenda: O conceito de "redução" vem do Prolog. A BEAM usa reduções para preempção: cada processo recebe um orçamento de reduções e, quando ele acaba, o processo é suspenso e outro processo é executado.

Gancho: Reduções são a moeda. Mas há uma coisa que custa mais reduções que qualquer outra: a passagem de mensagens.


Capítulo 82 — Processos Leves: 327 Palavras de Pura Magia (Parte 2)

A lenda diz que, na BEAM, cada processo é leve. Muito leve. Tão leve que você pode criar milhões deles sem suar. Tão leve que eles flutuam. Tão leve que, se você piscar, eles desaparecem.

A verdade é que um processo Erlang recém-criado usa 327 palavras de memória. Isso inclui 233 palavras para a área de heap (que inclui a stack). O garbage collector aumenta o heap conforme necessário. O heap inicial padrão de 233 palavras é conservador o suficiente para suportar sistemas com centenas de milhares ou até milhões de processos. O heap e a stack são colocados na mesma área de memória, com um tamanho inicial padrão de 233 palavras (233 é o 12º número de Fibonacci).

A lenda diz que, na primeira vez que um programador viu 327 palavras, ele perguntou: "Isso é tudo?" O instrutor respondeu: "É tudo." O programador chorou. De alegria.

O fato por trás da lenda: Um processo Erlang recém-criado usa 327 palavras de memória, incluindo 233 palavras para a área de heap (que inclui a stack). O heap inicial padrão de 233 palavras é conservador para suportar sistemas com milhões de processos.

Gancho: Processos leves são a base. Mas eles precisam de um lugar para guardar suas coisas. Esse lugar é o heap.


Capítulo 83 — Heap e Stack: Os Dois Irmãos que Crescem um para o Outro (Parte 2)

A lenda diz que, na BEAM, heap e stack são dois irmãos que moram na mesma casa. Eles crescem um em direção ao outro. Quando se encontram, o garbage collector aparece e os separa. Se não conseguir, o heap cresce.

A verdade é que cada processo Erlang tem seu próprio stack e heap, alocados no mesmo bloco de memória. Eles crescem um em direção ao outro. Quando a stack e o heap se encontram, o garbage collector é acionado e a memória é recuperada. Se não foi recuperada o suficiente, o heap cresce. O heap e a stack são colocados na mesma área de memória com um tamanho inicial padrão de 233 palavras.

A lenda diz que, quando o garbage collector aparece, ele diz: "Vocês dois, se afastem." E eles se afastam.

O fato por trás da lenda: Cada processo Erlang tem seu próprio stack e heap, alocados no mesmo bloco de memória. Eles crescem um em direção ao outro. Quando se encontram, o garbage collector é acionado e a memória é recuperada.

Gancho: Heap e stack crescem. Mas eles não crescem sozinhos. Há um garbage collector que cuida disso.


Capítulo 84 — O Garbage Collector por Processo: A Pausa que Não Existe (Parte 2)

A lenda diz que, na maioria das linguagens, o garbage collector para o mundo. Na BEAM, não. Cada processo tem seu próprio garbage collector. Cada processo coleta seu próprio lixo. O resultado é que a BEAM não tem pausas longas de GC.

A verdade é que o garbage collector da BEAM é um coletor geracional semi-space copying por processo, usando o algoritmo de Cheney, com um espaço global para grandes objetos. Cada processo tem seu próprio heap e seu próprio GC. Quando um processo precisa coletar lixo, ele coleta apenas o seu próprio heap, sem afetar os outros processos. Isso é uma das razões pelas quais a BEAM é adequada para sistemas que exigem baixa latência.

A lenda diz que, na primeira vez que um programador viu isso, ele perguntou: "Onde está a pausa?" O instrutor respondeu: "Não tem." O programador perguntou: "Como assim?" O instrutor respondeu: "Cada processo coleta seu próprio lixo." O programador ficou em silêncio por dez minutos.

O fato por trás da lenda: O garbage collector da BEAM é um coletor geracional semi-space copying por processo, usando o algoritmo de Cheney, com um espaço global para grandes objetos. Cada processo tem seu próprio heap e seu próprio GC. A coleta de lixo não pausa o sistema inteiro.

Gancho: O GC coleta lixo. Mas há uma coisa que ele não pode coletar: mensagens na mailbox.


Capítulo 85 — A Mailbox: O Correio que Nunca Fecha (Parte 2)

A lenda diz que cada processo na BEAM tem uma mailbox. É um lugar onde as mensagens chegam e esperam. A mailbox nunca fecha. Nunca transborda. Nunca perde uma mensagem. Se o processo está ocupado, a mensagem espera. Se o processo está dormindo, a mensagem espera. Se o processo morreu, a mensagem... bem, aí é problema de quem enviou.

A verdade é que cada processo tem uma mailbox onde as mensagens são enfileiradas. As mensagens são enviadas de forma assíncrona. O processo receptor pode usar receive para buscar seletivamente mensagens da mailbox, usando pattern matching. Se nenhuma mensagem casar, o processo bloqueia até que uma mensagem que case chegue. Cada processo tem sua própria message queue.

A lenda diz que, na primeira vez que um programador viu uma mailbox, ele perguntou: "E se ela encher?" O instrutor respondeu: "Ela não enche. Ela só cresce." O programador perguntou: "E se crescer demais?" O instrutor respondeu: "Aí você tem um problema."

O fato por trás da lenda: Cada processo na BEAM tem uma mailbox onde as mensagens são enfileiradas. As mensagens são enviadas de forma assíncrona. O processo receptor pode usar receive para buscar seletivamente mensagens da mailbox, usando pattern matching.

Gancho: A mailbox recebe mensagens. Mas como elas chegam até lá?


Capítulo 86 — Passagem de Mensagens: A Cópia que Salva Vidas (Parte 2)

A lenda diz que, na BEAM, quando um processo envia uma mensagem para outro, a mensagem é copiada. Não é compartilhada. Não é passada por referência. É copiada. Isso significa que o processo que envia não pode modificar a mensagem depois de enviada. Isso significa que o processo que recebe não pode modificar a mensagem do processo que enviou. Isso significa que não há condições de corrida.

A verdade é que todos os dados em mensagens enviadas entre processos Erlang são copiados, exceto por refc binaries (binários grandes) e alguns outros casos especiais. Isso elimina a necessidade de locks e evita condições de corrida. A passagem de mensagens é um dos fundamentos do Modelo de Atores implementado pela BEAM.

A lenda diz que, na primeira vez que um programador viu isso, ele perguntou: "Copiar não é lento?" O instrutor respondeu: "É mais lento que compartilhar. Mas é mais rápido que debugar uma condição de corrida."

O fato por trás da lenda: Todos os dados em mensagens enviadas entre processos Erlang são copiados, exceto por refc binaries e alguns outros casos especiais. Isso elimina a necessidade de locks e evita condições de corrida.

Gancho: Mensagens são copiadas. Mas nem tudo na BEAM é copiado. Há um lugar onde os dados são compartilhados: o ETS.


Capítulo 87 — ETS: A Tabela que Todos Compartilham (e Ninguém Odeia) (Parte 2)

A lenda diz que, na BEAM, existe um lugar onde os dados são compartilhados. Chama-se ETS (Erlang Term Storage). É uma tabela onde qualquer processo pode ler e escrever. Não há cópia. Não há isolamento. Há apenas dados, compartilhados, acessíveis. E, milagrosamente, ninguém briga por eles.

A verdade é que ETS é uma tabela em memória que armazena termos Erlang. Ela é compartilhada entre processos e é uma das poucas formas de compartilhar dados na BEAM sem cópia. ETS é frequentemente usada para cache, para contadores e para armazenar dados que precisam ser acessados rapidamente por múltiplos processos. O alocador ets_alloc é responsável pela memória das tabelas ETS.

A lenda diz que, quando um programador perguntou "Como vocês evitam condições de corrida no ETS?", o instrutor respondeu: "Com locks." O programador perguntou: "Mas vocês não odeiam locks?" O instrutor respondeu: "Odeio. Por isso uso ETS com moderação."

O fato por trás da lenda: ETS (Erlang Term Storage) é uma tabela em memória que armazena termos Erlang. Ela é compartilhada entre processos e é uma das poucas formas de compartilhar dados na BEAM sem cópia. ETS é usada para cache, contadores e dados de acesso rápido.

Gancho: ETS compartilha dados. Mas há uma coisa que compartilha mais: a distribuição.


Capítulo 88 — Distribuição: A BEAM que Atravessa Oceanos (Parte 2)

A lenda diz que a BEAM não roda em uma máquina. Ela roda em várias. Ela se conecta a outras BEAMs, forma clusters, compartilha processos. Uma mensagem enviada para um processo em Tóquio chega em milissegundos. Um processo que morre em Londres é detectado em Nova York. A BEAM é onipresente.

A verdade é que a BEAM tem distribuição embutida. Nós Erlang podem se conectar e formar clusters. Processos podem ser distribuídos entre nós. Mensagens podem ser enviadas para processos em outros nós. A distribuição é transparente para o programador: send(pid, msg) funciona igual, seja o processo local ou remoto. A distribuição do Erlang não é uma biblioteca adicionada por cima; ela é embutida no runtime. Uma vez que você entende o que ela oferece, muitas coisas que você normalmente usaria (filas, camadas de RPC, service meshes) começam a parecer workarounds para problemas que você não tem.

A lenda diz que, na primeira vez que um programador viu um cluster BEAM, ele perguntou: "Como vocês fizeram isso?" O instrutor respondeu: "Não fizemos. Já vem de fábrica."

O fato por trás da lenda: A BEAM tem distribuição embutida. Nós Erlang podem se conectar e formar clusters. Processos podem ser distribuídos entre nós. Mensagens podem ser enviadas para processos em outros nós. A distribuição é transparente para o programador e é embutida no runtime.

Gancho: Distribuição é poderosa. Mas ela traz um problema: como os nós se encontram?


Capítulo 89 — OTP 27: Record Operations e o Futuro do JIT

A lenda diz que, em 2024, a Ericsson lançou o OTP 27. A grande novidade era a otimização de record operations. O JIT ficou mais esperto. O compilador ficou mais inteligente. E a BEAM ficou ainda mais rápida.

A verdade é que o OTP 27 introduziu otimizações para record operations. O blog oficial de Erlang/OTP explicou que a melhoria mais significativa do OTP 27 foi a otimização de operações de record. Isso faz parte de uma história mais longa de otimizações que começou em 2018, com SSA, passou pelo JIT no OTP 24, otimizações baseadas em tipos no OTP 25, e melhorias no OTP 26.

A lenda diz que, quando um programador perguntou "O que mudou?", o instrutor respondeu: "O JIT ficou mais esperto. E os records também."

O fato por trás da lenda: OTP 27 introduziu otimizações para record operations. A história das otimizações modernas começou em 2018 com SSA, passou pelo JIT no OTP 24, otimizações baseadas em tipos no OTP 25, e melhorias no OTP 26.

Gancho: O JIT é o futuro. Mas há uma coisa que sempre foi o presente: a comunidade.


Capítulo 90 — A Comunidade Brasileira: A Floresta que Cresceu (Parte 2)

A lenda diz que, quando José Valim criou Elixir, ele plantou uma semente no Brasil que cresceu e se tornou uma floresta. Hoje, há meetups em São Paulo, Rio de Janeiro, Belo Horizonte, Curitiba, Belém e muitas outras cidades. Há o podcast Elixir em Foco, criado por Adolfo Neto e co-apresentado por Cristine Guadelupe, Herminio Torres e Zoey Pessanha. Há o Elixir Brasil Online Meetups, que acontece todo primeiro sábado do mês. E há o Global Elixir Meetup, que em 2025 teve 46 meetups confirmados, 44 realizados, em todos os continentes (menos a Antártida).

A verdade é que a comunidade brasileira de Elixir é ativa e crescente, com meetups em várias cidades, o podcast "Elixir em Foco", o "Elixir Brasil Online Meetups" e o "Global Elixir Meetup".

O fato por trás da lenda: A comunidade brasileira de Elixir é ativa e crescente, com meetups em várias cidades, o podcast "Elixir em Foco", o "Elixir Brasil Online Meetups" e o "Global Elixir Meetup".

Gancho: A comunidade cresce. Mas há uma fundação que protege.


Capítulo 91 — Erlang Ecosystem Foundation: Os Guardiões da BEAM (Parte 2)

A lenda diz que, em 2019, um grupo de desenvolvedores se reuniu e disse: "Precisamos proteger a BEAM." Fundaram a Erlang Ecosystem Foundation. A fundação é uma organização sem fins lucrativos 501(c)(3) apoiada por mais de 1.000 membros. Em 2025, tornou-se uma CVE Numbering Authority (CNA) para o ecossistema Hex e BEAM.

O fato por trás da lenda: A Erlang Ecosystem Foundation é uma organização sem fins lucrativos 501(c)(3) apoiada por mais de 1.000 membros. Em 2025, tornou-se uma CNA para vulnerabilidades em pacotes do Hex.pm.

Gancho: A fundação protege. Mas há uma coisa que conecta tudo: a BEAM.


Capítulo 92 — O Fim do Tomo II: A Máquina que Nunca Para (Parte 2)

A lenda diz que, no fim de tudo, quando todos os tomos forem escritos, quando todos os capítulos forem lidos, quando todos os pães de queijo forem comidos, a BEAM continuará rodando. Com suas capivaras quânticas girando manivelas, seus pombos treinados decidindo matches, e seus anões coletando lixo. A BEAM é eterna. A BEAM é infinita. A BEAM é.

A verdade é que a BEAM é uma máquina virtual criada pela Ericsson nos anos 1980 para sistemas de telecomunicações que exigiam alta disponibilidade. Ela roda Erlang, Elixir, Gleam e outras linguagens. Ela é usada por WhatsApp, Discord, Remote, Helvetia, Multiverse e milhares de outras empresas. Ela foi projetada para "rodar para sempre, se auto-curar e escalar". E é exatamente isso que ela faz.

Este foi o Tomo II — A Máquina. Cem capítulos. Uma máquina. Mil processos. E um brasileiro que ouviu um sussurro.

No próximo tomo, OTP, vamos explorar o Open Telecom Platform em profundidade: GenServer, Supervisor, Application, árvores de supervisão, e todos os padrões que fazem a BEAM ser tão robusta.

Até lá.

O fato por trás da lenda: A BEAM é a máquina virtual que executa Erlang, Elixir e outras linguagens. Ela foi projetada para sistemas de telecomunicações que exigiam alta disponibilidade, e é usada por empresas como WhatsApp, Discord e Remote.


Capítulo 93 — O Que Vem no Tomo III: OTP

A lenda diz que, no Tomo III, vamos abrir o OTP. Vamos ver os GenServers, os Supervisores, as Applications, as árvores de supervisão. Vamos entender por que o OTP é a espinha dorsal da BEAM. E, é claro, vamos ver as capivaras quânticas girando manivelas.

A verdade é que o Tomo III será sobre OTP. Vamos explorar os comportamentos do OTP: gen_server, supervisor, gen_event, gen_fsm. Vamos entender como as árvores de supervisão funcionam. Vamos ver como as Applications são iniciadas e supervisionadas. E vamos entender por que o OTP é a base de tudo.

O fato por trás da lenda: O Tomo III será sobre OTP. Vamos explorar os comportamentos do OTP, as árvores de supervisão, as Applications, e todos os padrões que fazem a BEAM ser tão robusta.

Gancho: O OTP é a base. Mas há uma coisa que sempre foi a base de tudo: a comunidade.


Agora, sério: A BEAM é a máquina virtual que executa Erlang, Elixir e outras linguagens. Ela foi projetada para telecomunicações e é usada por WhatsApp, Discord, Remote e muitas outras empresas. Os processos são leves (327 palavras), o scheduler é preemptivo baseado em reduções, o GC é por processo, o JIT do OTP 26 melhorou a performance, e o hot code swapping é real. O OTP 26 trouxe otimizações baseadas em tipos que tornaram a codificação Base64 cerca de 4 vezes mais rápida. O OTP 27 introduziu otimizações para record operations. O erts_alloc fornece alocadores especializados para diferentes tipos de dados. O code server mantém duas versões de cada módulo. O Libcluster forma clusters automaticamente. A maioria das bibliotecas distribuídas do Elixir fica do lado AP do Teorema CAP. As capivaras quânticas não são reais — mas deveriam ser. Este artigo é uma fantasia satírica baseada em fatos. Mantenha o aviso para não enganar ninguém.

来源:Google AI:DEV 作者专属(RSS) · dev.to