20 pontos por GN⁺ 2025-08-16 | 3 comentários | Compartilhar no WhatsApp
  • What the Fork é uma ferramenta multiplataforma que visualiza em tempo real diversos processos de build, como C/C++/Rust
  • Permite identificar facilmente problemas estruturais em sistemas de build existentes, como falta de paralelismo e processos ineficientes
  • Funciona com qualquer sistema de build e linguagem de programação, com suporte a diversas ferramentas de build como make, ninja, gradle, zig e cargo
  • Por meio de monitoramento de chamadas de sistema, visualiza em caixas o tempo de execução, os comandos e as relações de dependência de cada processo
  • Uma ferramenta muito útil para otimização de builds, análise de gargalos e melhoria de desempenho de CI

Introdução e contexto

  • What the Fork é uma ferramenta de visualização de builds em tempo real criada para diagnosticar visualmente as causas de lentidão em builds
  • Em projetos como o LLVM, a compilação pode ser lenta pelo próprio volume de código, mas na maioria dos casos os builds demoram desnecessariamente por causa de configurações ineficientes
  • Até agora, era difícil verificar diretamente os problemas de um build ou enxergar rapidamente problemas estruturais de forma consolidada, por isso havia necessidade de uma ferramenta assim
  • A ferramenta foi projetada para ser multiplataforma e pode ser aplicada a qualquer sistema de build e linguagem

Principais recursos e modo de uso

  • What the Fork não é apenas um profiler de sistema genérico, mas uma ferramenta voltada ao diagnóstico de problemas específicos de build
  • Exemplos incluem detectar o não uso da flag -j no make, concentração excessiva de tempo em um arquivo ou etapa de compilação específica, e comandos que rodam em sequência mesmo quando poderiam ser paralelizados
  • É especialmente eficaz para análise e otimização do desempenho de clean builds em ambientes de CI
  • O modo de uso é executar o comando wtf antes do comando de build (ex.: wtf make, wtf cargo build, wtf npm run build)
  • Quando o build começa, a interface é iniciada e atualiza em tempo real o andamento de cada processo

UI e forma de visualização

  • Cada processo de build é exibido na linha do tempo em formato de caixa, com diferenciação por cores conforme o tipo
  • A relação entre processos pai e filho é representada por uma estrutura aninhada
  • No painel inferior, são exibidos o tempo de execução, o diretório de trabalho e os argumentos completos de comando do processo selecionado

Como funciona

  • Um build é uma combinação de vários processos (ex.: bash, clang, ld)
  • Builds de grande porte usam diversas ferramentas como cargo, make, bazel, gradle e xcodebuild, que na prática executam muitos comandos, dependências, cache e tarefas de agendamento
  • Apenas com a saída do terminal não é possível entender processos aninhados (por exemplo, ld sendo chamado internamente por clang) nem a estrutura detalhada de temporização
  • Para isso, a ferramenta utiliza chamadas de sistema que detectam o início e o fim de processos em cada sistema operacional (macOS: Endpoint Security API, Linux: ptrace(), Windows: Event Tracing for Windows etc.)
  • Dessa forma, é possível reconstruir todo o processo de build e sua linha do tempo, além de identificar o caminho de execução e o tempo de cada etapa
  • Também pode ser usado para rastrear diversos subprocessos além de builds

Casos reais e observações

  • Vários engenheiros (da Delta, Mozilla e Apple) aplicaram a ferramenta em projetos reais e encontraram problemas inesperados
  • Exemplo 1: em um projeto open source que usa Cargo, foi constatado que os arquivos estavam sendo compilados em sequência, revelando falta de paralelismo (com um CPU de 10 núcleos, havia potencial para mais de 10x de melhoria de velocidade)
  • Exemplo 2: em um build do LLVM com Ninja, todos os núcleos de CPU estavam executando tarefas em paralelo de forma eficiente, atingindo uma eficiência de build próxima do ideal
  • Exemplo 3: em um projeto baseado em CMake, foi descoberta uma estrutura ineficiente em que execuções aninhadas de cmake/make/clang e revalidações de versão de Xcode/OS se repetiam 85 vezes (o trabalho real era mínimo)
  • Exemplo 4: em um grande projeto Objective-C usando xcodebuild, foi observada falta de paralelismo no fim do build e um período de 6 segundos de inatividade antes do início; em comparação, o ninja começava a compilar após apenas 0,4 segundo
  • Exemplo 5: ao compilar o Orca Project com Zig, a ordem de build das dependências era definida aleatoriamente, fazendo com que a eficiência do paralelismo variasse conforme a sorte. Observou-se que algumas dependências eram executadas por último, reduzindo o paralelismo
  • Exemplo 6: no projeto GitHub CLI com make/go, o tempo de download de dependências era alto. Reduzir dependências pode melhorar a velocidade de build

Efeitos de uso e limitações

  • A análise visual da linha do tempo permite identificar gargalos inesperados, repetições desnecessárias de dependências e áreas com pouco paralelismo
  • É possível encontrar rapidamente pontos de melhoria estrutural, como problemas de dependência, retrabalho desnecessário e ineficiências de ferramentas específicas, usando isso diretamente para otimizar o desempenho do build
  • A visualização do comando completo de cada processo também permite análises mais detalhadas

Programa beta

  • What the Fork funciona em Windows, Linux e macOS
  • Pessoas e equipes que queiram enviar feedback podem se inscrever para a beta privada (há um link para formulário do Google)

3 comentários

 
brain1401 2025-08-17

O comando é engraçado demais kkk, wtf então...

 
t7vonn 2025-08-17

Seria ótimo se fosse open source.

 
GN⁺ 2025-08-16
Comentários do Hacker News
  • Atualmente estou preso em um ambiente onde só posso usar CMake, GCC e Unix Make, então é quase impossível obter informações detalhadas sobre por que o build é lento; é um build caótico, com etapas complexas como copiar arquivos do código-fonte para a pasta de build, várias linguagens (C, C++, Fortran, Python), etapas personalizadas do CMake etc. Se esta ferramenta funcionar bem mesmo nesse tipo de ambiente bagunçado, acho que eu poderia aprender muita coisa.

    • O tsoding escreveu uma biblioteca C de cabeçalho único para builds cross-platform em https://github.com/tsoding/nob.h; só precisa de cc. Dá para inspecionar as etapas do build usando ferramentas de profiling do GDB. Acho uma ideia legal. Talvez não sirva para o autor deste post, mas, se você precisa lidar com várias linguagens, Nix é uma excelente ferramenta de build.

    • Eu mesmo criei uma ferramenta de tracing/profiling de tempo de compilação como plugin do GCC. Se tiver interesse, veja: https://github.com/royjacobson/externis

    • Quando tentei reduzir o tempo de compilação do meu game engine, usei o tamanho dos artefatos compilados como métrica substituta. Como o tempo de relógio era muito instável, medir o tamanho dos binários resultantes — que era igual entre builds e até entre máquinas diferentes — acabou sendo mais fácil de lidar. Não bate 100%, mas foi útil na prática.

    • Estou passando por um problema parecido. Às vezes vejo o CMake recompilar até arquivos que eu nem modifiquei. Por exemplo, faço uma pequena mudança em um .cpp sem alterar a interface, e até objetos totalmente independentes são recompilados. Às vezes fico me perguntando se o CMake não está criando dependências mais fortes do que as dos arquivos reais, o que acaba alongando o tempo de build sem necessidade.

  • Eu sugeriria ao autor do blog mostrar no topo da página, logo abaixo do cabeçalho, o gif da gravação do build do app macOS. Fica melhor quando você mostra primeiro o resultado do que foi feito e depois vem com a explicação.

    • Boa sugestão. Atualizei o blog imediatamente para refletir isso.
  • Gostei muito deste projeto. Fiz algo parecido em 2018 usando strace, dtruss e https://buildinfer.loopperfect.com/ para coisas como geração automática de arquivos BUCK. Visualizei com graphviz, perfetto.dev etc. É uma pena que eu não tenha conseguido empacotar isso como um produto formal, mas em consultoria ajudou muito a diagnosticar causas e a migrar para BUCK/Bazel. Recentemente voltei a pensar nisso de novo, buscando aplicações mais amplas. Também há desafios técnicos intrínsecos nessa abordagem: quando os logs de system calls são gravados em disco, eles crescem para dezenas ou centenas de GB (por exemplo, llvm dá 50 GB, em alguns casos passa de 100 GB); também é preciso lidar bem com etapas de build via https, IPC e afins (no passado, um cliente chegava a puxar código de um banco Firebird via Perl toda vez que fazia build); e, por ser uma análise em runtime, ela precisa ser repetida para cada configuração de build.

    • Pergunta por curiosidade: como você fez o logging de system calls? Usou algum truque com LD_PRELOAD ou filtragem com eBPF?
  • Acho muito legal. Sempre senti que há muitos problemas que passam despercebidos por falta desse tipo de visualização. Ter uma ferramenta dessas teria ajudado muito quando eu estava otimizando o sistema de build do Mozilla, uns 10 anos atrás. Acho que o post teria ficado ainda melhor se mostrasse com mais detalhes quais problemas foram encontrados na prática.

    • (autor) Obrigado. Minha ligação com o engenheiro da Mozilla terminou de repente, então não consegui ouvir em detalhes quais problemas eles encontraram. Eu adoraria investigar isso diretamente.
  • Em projetos C++ gerenciados com CMake, já usei com sucesso ninjatracing e o -ftime-trace do Clang para visualizar performance de build. Além disso, com ClangBuildAnalyzer dá para analisar com mais granularidade onde o compilador está gastando tempo.

  • Achei muito legal. Existe algum plano de open source? Estou construindo algo parecido e gostaria de colaborar.

  • Se você usa o compilador Visual C++ no Windows, também recomendo vcperf. Ele já vem incluído no VS2022 ou pode ser compilado diretamente do GitHub. Já usei isso em projetos gerados por UBT e CMake. Não lembro se dá para avaliar diretamente a qualidade da paralelização do build, mas é fácil ver informações do frontend do compilador, especialmente para encontrar arquivos de cabeçalho muito incluídos ou intrinsecamente pesados.

    • Também recomendo o Incredibuild. Mesmo a versão gratuita já basta para visualizar o build e identificar gargalos.
  • Em geral isso passa despercebido, mas uma observação importante é que a lógica de build “baked in” (pré-calculada) no sistema de build não rastreia com granularidade quais mudanças realmente o afetam. Por exemplo, no ninja parte da lógica de build já é embutida previamente, o que o torna rápido. Eu fiz benchmark de build completo do Xerces-C++ com ninja (configurado via CMake) e com build2 (uma ferramenta que lida com configuração e rastreamento de mudanças dentro do próprio build): o ninja levou 3,23 s, o build2 3,54 s. Repetindo o build enquanto preservava parte dos arquivos gerados pelo CMake, caiu para 3,28 s. Já a etapa de configuração só do CMake levou 4,83 s. No fim, um build full-stack com CMake+ninja leva de fato uns 8 segundos, que costuma ser o tempo real percebido quando se usa isso como biblioteca.

    • O kbuild faz com que cada alvo no Make dependa de um arquivo dummy, para que mudanças em opções como CFLAGS sejam refletidas corretamente. Ele foi projetado para usar o Make de um jeito parecido com o ninja, sem colocar o grafo completo de build em cada processo do Make. Fico curioso para ver como isso se compararia na prática.
  • Já tentei algo parecido executando o Instruments durante o build para entender quais processos faziam o quê e em que momento. A desvantagem é que, quando o build demora muito, o Instruments começa a engasgar. Também é incômodo porque não há filtragem por árvore de processos, mas isso ajudou bastante quando o Twitter reduziu drasticamente o tempo de build do código iOS. Mais recentemente, o tracing de “All Processes” do Instruments quebrou, então esse método não é mais viável.

  • Parece muito legal. Existe alguma versão para macOS que já possa ser testada agora? Gostaria de usar isso também em trabalhos com Rust ou C++/Swift.

    • Não tenho planos de distribuir uma versão para macOS ao próximo grupo de beta testers depois de corrigir os bugs; se você se inscrever (no final do artigo) e mencionar este comentário, com certeza vou colocá-lo no grupo beta.

    • Ainda não parece haver release pública para nenhum OS; no momento só é possível solicitar early access.