- O projeto .NET Unified Build é um novo sistema de build que integra todo o produto no formato de um “repositório monolítico virtual (Virtual Monolithic Repository, VMR)” para reduzir a complexidade e a ineficiência da estrutura de build existente baseada em repositórios distribuídos
- A forma distribuída de composição do produto oferece alta independência e flexibilidade, mas traz um grande custo em gerenciamento de dependências, consistência de build e velocidade
- O Unified Build expande os princípios do Source Build para distribuições Linux, introduzindo um layout único de código-fonte e uma estrutura de “build vertical (Vertical Build)” para reduzir o tempo de build e aumentar a previsibilidade
- Por meio de fluxo de código bidirecional (two-way code flow), testes de cenário e melhorias na infraestrutura de validação e assinatura automáticas, ele aumenta ao mesmo tempo a eficiência dos desenvolvedores e a qualidade do produto
- Adotado oficialmente no .NET 10, esse sistema alcançou resultados concretos como redução do tempo de build (de 24 horas para menos de 7 horas), diminuição dos custos de manutenção e maior confiabilidade na distribuição
Contexto da mudança na estrutura de build do .NET
- Durante a abertura de código do .NET em 2015~2016, o desenvolvimento foi dividido em vários repositórios, como CoreCLR, CoreFX, ASP.NET Core e SDK
- Cada repositório fazia build e distribuição de forma independente, e o produto completo era montado por meio de um grafo de dependências
- Esse modelo é semelhante ao ecossistema OSS, mas em casos de patches de segurança ou correções urgentes, exigia coordenação simultânea entre várias equipes, o que tornava imprevisível o tempo necessário
- Apesar das vantagens do desenvolvimento distribuído, como camadas, segmentação da comunidade e desenvolvimento assíncrono, ele era ineficiente para garantir a consistência do produto (coherency)
Complexidade da composição do produto e overhead
- Complexidade (Complexity): definida como o número de etapas necessárias até que uma mudança chegue ao cliente
- Quanto mais repositórios e nós de dependência existirem, mais tempo e coordenação humana são necessários para garantir consistência
- Overhead: tempo que não produz diretamente entregáveis que possam ser enviados ao cliente
- Ex.: criação de PR, espera por aprovação, enfileiramento, configuração de ambiente etc.
- A análise do build do runtime do .NET 8 mostrou que cerca de 38,5% do tempo total de build era overhead
- Quando complexidade e overhead se combinam, a eficiência do build cai drasticamente e o ciclo completo de release fica mais longo
Origem do Source Build e do Unified Build
- O Source Build é um sistema projetado para que distribuições Linux possam fazer o build offline do .NET a partir de uma única fonte
- Princípios de implementação única, plataforma única e ambiente único de build
- Um orquestrador de build gerencia as dependências e a ordem de build de cada componente
- O Source Build consegue compilar em até 50 minutos com baixa complexidade e baixo overhead
- Tentou-se aplicar esse conceito também ao build interno da Microsoft, mas havia dificuldades por causa de código fechado, dependências legadas e joins entre plataformas
- Para resolver isso, foram adotadas abordagens como pacotes de referência apenas para Source Build (source-build-reference-packages), princípio de implementação única e eliminação de joins
Objetivos e design do Unified Build
- Tornar possível fazer o build de todo o produto .NET com um único commit
- Gerar todas as distribuições por plataforma em um único ambiente
- Permitir build e validação independentes fora da Microsoft
- Sincronizar automaticamente mudanças entre o VMR e os repositórios individuais por meio de fluxo de código bidirecional
- Executar validação funcional em nível de produto completo por meio de testes de cenário
- Paralelizar builds por plataforma com a estrutura de build vertical (Vertical Build)
- Composta por cerca de 35 a 40 verticais de build (short/tall stack)
Etapas de implementação do Unified Build
- .NET 7: concepção e aprovação do conceito
- .NET 8: melhoria da infraestrutura do Source Build e construção da base
- .NET 9: experimentos com build vertical e fluxo de código
- .NET 10: productização oficial e incorporação ao RTM
- Novo processo de build introduzido no Preview 4, com transição completa a partir do Preview 5
Componentes principais
Virtual Monolithic Repository (VMR)
- O repositório dotnet/dotnet atua como layout único de código-fonte para todos os componentes
- Os desenvolvedores podem trabalhar tanto em repositórios individuais quanto no VMR, obtendo ao mesmo tempo a flexibilidade do modelo distribuído e a consistência do modelo monolítico
Vertical Build
- Cada plataforma e runtime é compilado de forma independente
- Após os builds paralelos, os resultados são integrados, e alguns joins são tratados em passes adicionais de build
Code Flow
- Sincronização bidirecional de código: repositórios de componentes → VMR, VMR → repositórios de componentes
- O último estado do fluxo de código é registrado em
eng/Version.Details.xml
- As mudanças são geradas como arquivos de patch para criação automática de PRs
- Há lógica embutida para tratamento de conflitos e recuperação de erros
Scenario Test Validation
- Além dos testes unitários existentes, foram adicionados testes de cenário que validam a funcionalidade do produto como um todo
- Eles são executados com base nos artefatos de build, reforçando a prevenção de regressões e a garantia de qualidade
Resultados e efeitos
- Redução do tempo de build: de mais de 24 horas para menos de 7 horas (incluindo assinatura)
- Maior flexibilidade: ciclos de build e distribuição mais curtos, com aplicação mais fácil de correções urgentes
- Mais previsibilidade: clareza sobre quando o build será concluído após uma mudança
- Melhoria de infraestrutura: ferramentas de assinatura, logs, builds paralelos, automação do fluxo de dependências etc.
- O Source Build para distribuições Linux também permanece sempre em estado limpo antes do build
Direção futura
- No .NET 11, está prevista a introdução de automação do fluxo de código e agentes de monitoramento baseados em IA
- Automação do rastreamento de erros no processo de PR → incorporação ao produto
- No longo prazo, pretende-se simplificar o build e aumentar a velocidade com a eliminação dos pontos de join
- Meta: build completo em até 4 horas
Conclusão
- O Unified Build, que superou as limitações do modelo de build distribuído, melhora de forma fundamental a eficiência de build e distribuição do .NET
- Houve progresso real em três eixos: redução de complexidade e overhead, mais consistência, velocidade e qualidade
- A partir do RTM do .NET 10, esse sistema passou a ser aplicado integralmente, com melhorias contínuas previstas para as próximas versões
1 comentários
Comentários do Hacker News
Eu realmente admiro a equipe do .NET
Eles publicam textos técnicos profundos com frequência e a obsessão deles por otimização de desempenho é impressionante (por exemplo, a evolução do Kestrel e do Entity Framework)
O ASP.NET é um dos poucos projetos grandes que sobreviveu até mesmo a uma mudança do porte de Python 2→3
Antes ele dependia de recursos quase mágicos para sincronização de sessão, mas agora funciona de uma forma completamente diferente
É bom sentir que uma empresa de 3 trilhões de dólares está genuinamente tentando melhorar a stack que eu uso
Então troquei por Dapper e um sistema de migração feito por mim, e o tempo de validação e seeding do banco na inicialização caiu de 10 segundos para menos de 2 segundos (em hardware fraco + SQLite)
As queries geradas pelo Entity tinham joins múltiplos desnecessários demais
Hoje estou migrando para um backend simples em Go, e uso .NET só em outras soluções
Frameworks como WPF tinham tantos problemas que era preciso fazer hacks em Win32
Por exemplo, só no .NET 9 ele finalmente retorna todas as interfaces de rede corretamente. Os runtimes anteriores expunham apenas as NICs ativas
Ainda tenho projetos que precisam manter suporte ao Windows 7
Mesmo em projetos novos ainda há casos em que é preciso usar .NET 4.8. Por exemplo, ao montar fórmulas do Excel surgem problemas de deadlock com async/await
Além disso, integrações do Windows quebram, então a mesma chamada de rede autentica no 4.8 mas falha no Core
A quebra de compatibilidade retroativa em inúmeras bibliotecas dificulta muito a migração
O desempenho melhorou, mas em termos de funcionalidades o .NET Framework parece fossilizado
Levou 15 anos para um serializador JSON entrar na biblioteca padrão, e ainda não há suporte a formatos de imagem modernos como webp ou heic
O Visual Studio exibe mensagens de crash praticamente todo dia
Eu era um fã fervoroso de .NET, mas sinto falta da liderança do Anders
Num projeto paralelo recente, desenvolvi um backend de API REST em C# no VSCode do macOS e já o mantenho em produção no Linux há 3 anos
Uso SQLite, EFCore e Minimal API, e a experiência é muito mais tranquila do que a do frontend (NextJS/React/MaterialUI, com mais de 50 pacotes npm)
Pessoalmente, é meu framework de API favorito
A segunda melhor opção seria a combinação TS + Hono + Zod-OpenApi + SwaggerUI, mas configurar o contexto de tipos é um pouco trabalhoso
Achei impressionante que a base para a abertura do código e o suporte multiplataforma do .NET tenha sido o sistema de build das distribuições Linux
Por isso era necessário um sistema de build que atendesse às exigências deles, e no fim integrar tudo ao modelo das distribuições Linux era o único caminho viável
Esse modelo é simples, mas tem desempenho inferior. Um sistema de build distribuído com cache seria mais rápido, mas não se encaixa no fluxo de trabalho dos mantenedores
Concluímos que otimizar para simplicidade era melhor para incentivar a participação da comunidade
O objetivo é permitir que a própria comunidade faça build e distribuição para plataformas variadas, como BSD, S390x e outras
A quantidade de pull requests e resultados positivos dos últimos 10 anos é impressionante
Não imaginei que o texto de engenharia de software mais marcante que eu leria este ano viria da Microsoft
Eu gosto das versões recentes do .NET, mas achava que a robustez dele era meio acidental
Só que este texto mostra um esforço sistemático para melhorar a qualidade (incluindo diagramas e até casos de uso com LLM)
Mesmo que esse tipo de investimento diminua no futuro, isso continua sendo um ótimo exemplo de “como fazer”
As pessoas que participaram desse projeto provavelmente tiveram uma experiência incrível
O texto foi bom, mas acho que a equipe do .NET precisa abandonar o Azure DevOps
O maior gargalo é o tempo de espera na fila. Eles precisam rodar servidores de build bare metal
O hardware Mac conecta e inicia rapidamente
Nós subimos uma VM limpa para cada job para garantir conformidade e estabilidade
Manter máquinas quentes pré-preparadas eliminaria a espera, mas o custo é alto demais
Como é difícil manter vários SKUs diferentes sempre em espera, acabamos chegando a esse meio-termo
Fico me perguntando por que a Developer Division da Microsoft é de nível mundial, enquanto o restante da empresa virou símbolo de incompetência e burocracia
Desde que Bill saiu, a cultura de olhar para si mesma desapareceu
Acho que a raiz do problema está numa mentalidade de abstração em primeiro lugar, tentando simplificar sistemas complexos
Em vez de querer resolver tudo no nível mais alto, uma abordagem de baixo para cima pode eliminar muito mais problemas pela raiz
Ao ler a frase “compilamos de 3 a 4 versões principais e dezenas de bandas de SDK por mês”, fiquei me perguntando por que há tantas variações
Além disso, cada versão compila SDK/aspnet/runtime para várias plataformas, como x64/arm32/arm64 e Linux/macOS/Windows
Antes de o Node virar moda, .NET era uma opção sólida para construir backends (e o desempenho também era melhor que o do Node)
Depois dos ataques à cadeia de suprimentos no ecossistema Node, espero que muitos desenvolvedores voltem para plataformas estáveis
A grande mudança foi a transição para .NET Core, mas isso já foi há quase 10 anos
Atualizar framework e dependências dá um pouco de trabalho, mas ainda é muito mais tranquilo do que atualizar projetos em React
Com o ciclo curto de LTS, não é difícil manter tudo atualizado. Em ciclos rápidos de desenvolvimento, esse tipo de manutenção é normal
Na prática, o foco continua em Node.js, Java e low-code (iPaaS)
Ainda assim, às vezes aparecem oportunidades de sugerir add-ons em C++ por causa de problemas de desempenho