- El proyecto .NET Unified Build es un nuevo sistema de compilación que integra todo el producto en la forma de un "repositorio monolítico virtual (Virtual Monolithic Repository, VMR)" para reducir la complejidad y la ineficiencia de la estructura de compilación existente basada en repositorios distribuidos
- La estructura distribuida de composición del producto existente ofrece alta independencia y flexibilidad, pero genera una gran carga en términos de gestión de dependencias, coherencia de compilación y velocidad
- Unified Build amplía los principios de Source Build para distribuciones Linux, introduciendo un diseño de fuente único y una estructura de "compilación vertical (Vertical Build)" para acortar los tiempos de compilación y lograr mayor previsibilidad
- Mediante flujo de código bidireccional (two-way code flow), pruebas de escenarios y mejoras en la infraestructura de validación automática y firma, mejora al mismo tiempo la eficiencia de los desarrolladores y la calidad del producto
- Este sistema, adoptado oficialmente en .NET 10, logró resultados concretos como reducción del tiempo de compilación (de 24 horas a menos de 7), menores costos de mantenimiento y mayor confiabilidad en la distribución
Antecedentes del cambio en la estructura de compilación de .NET
- Durante su proceso de código abierto en 2015~2016, .NET se desarrolló dividido en múltiples repositorios como CoreCLR, CoreFX, ASP.NET Core y SDK
- Cada repositorio se compila y distribuye de forma independiente, y el producto completo se arma mediante un grafo de dependencias
- Este enfoque es similar al ecosistema OSS, pero en casos de parches de seguridad o correcciones urgentes requiere coordinación simultánea entre varios equipos, lo que provoca problemas de imprevisibilidad en los tiempos
- A pesar de las ventajas del desarrollo distribuido (capas, segmentación de la comunidad, desarrollo asíncrono, etc.), resulta ineficiente para garantizar la coherencia del producto (coherency)
Complejidad de la composición del producto y sobrecarga
- Complejidad (Complexity): se define como la cantidad de pasos necesarios para que un cambio llegue al cliente
- Cuantos más repositorios y nodos de dependencia haya, más tiempo y coordinación humana se requieren para garantizar la coherencia
- Sobrecarga (Overhead): tiempo que no produce directamente entregables que puedan llegar al cliente
- Ej.: creación de PR, espera de aprobación, encolado, configuración del entorno, etc.
- Según el análisis de compilación del runtime de .NET 8, aproximadamente el 38.5% del tiempo total de compilación era sobrecarga
- Cuando complejidad y sobrecarga se combinan, la eficiencia de compilación cae drásticamente y el ciclo completo de lanzamiento se alarga
Origen de Source Build y Unified Build
- Source Build es un sistema diseñado para que las distribuciones Linux puedan compilar .NET desde una única fuente y sin conexión
- Principios de implementación única, plataforma única y entorno de compilación único
- Un orquestador de compilación administra las dependencias y el orden de compilación de cada componente
- Source Build puede completarse en menos de 50 minutos gracias a su baja complejidad y baja sobrecarga
- Se intentó aplicar este concepto también a las compilaciones internas de Microsoft, pero existían dificultades por código cerrado, dependencias heredadas y joins entre plataformas
- Para resolverlo, se introdujeron enfoques como paquetes solo de referencia (source-build-reference-packages), el principio de implementación única y la eliminación de joins
Objetivos y diseño de Unified Build
- Poder compilar todo el producto .NET con un solo commit
- Generar todas las distribuciones por plataforma desde un único entorno
- Permitir compilación y validación independientes también fuera de Microsoft
- Sincronizar automáticamente los cambios entre el VMR y los repositorios individuales mediante flujo de código bidireccional
- Realizar validación funcional a nivel de producto completo mediante pruebas de escenarios
- Paralelizar las compilaciones por plataforma con una estructura de compilación vertical (Vertical Build)
- Compuesta por unas 35~40 verticales de compilación (
short/tall stack)
Etapas de implementación de Unified Build
- .NET 7: diseño conceptual y aprobación
- .NET 8: mejora de la infraestructura de Source Build y construcción de la base
- .NET 9: experimentos con compilación vertical y flujo de código
- .NET 10: conversión en producto oficial e incorporación en RTM
- Se introdujo el nuevo proceso de compilación en Preview 4 y la transición completa comenzó desde Preview 5
Componentes principales
Virtual Monolithic Repository (VMR)
- El repositorio dotnet/dotnet actúa como diseño de fuente único para todos los componentes
- Los desarrolladores pueden trabajar en repositorios individuales o en el VMR, logrando al mismo tiempo la flexibilidad del modelo distribuido y la coherencia del modelo monolítico
Vertical Build
- Se realiza una compilación independiente para cada plataforma y runtime
- Después de compilar en paralelo, los resultados se integran y algunos joins se manejan con pases de compilación adicionales
Code Flow
- Sincronización bidireccional de código: repositorios de componentes → VMR, VMR → repositorios de componentes
- El último estado del flujo de código se registra en
eng/Version.Details.xml
- Los cambios se generan como archivos de parche para crear PR automáticos
- Incluye lógica integrada para manejo de conflictos y recuperación de errores
Scenario Test Validation
- Además de las pruebas unitarias existentes, se agregan pruebas de escenarios que validan la funcionalidad del producto completo
- Se ejecutan con base en los artefactos de compilación, reforzando la prevención de regresiones y la garantía de calidad
Resultados y efectos
- Reducción del tiempo de compilación: de más de 24 horas a menos de 7 horas (incluyendo firma)
- Mayor flexibilidad: ciclos de compilación y distribución más cortos, y mayor facilidad para reflejar correcciones urgentes
- Mayor previsibilidad: claridad sobre cuándo terminará la compilación después de un cambio
- Mejoras de infraestructura: herramientas de firma, logs, compilación en paralelo, automatización del flujo de dependencias, etc.
- Source Build para distribuciones Linux también se mantiene siempre en un estado limpio antes de compilar
Dirección futura
- En .NET 11 está previsto incorporar automatización del flujo de código y agentes de monitoreo basados en IA
- Se automatizará el rastreo de errores en el proceso PR→integración al producto
- A largo plazo, se busca simplificar la compilación y mejorar la velocidad eliminando los puntos de join
- Objetivo: compilación completa en menos de 4 horas
Conclusión
- Unified Build, que superó las limitaciones del modelo de compilación distribuido, mejora de forma fundamental la eficiencia de compilación y distribución de .NET
- Logró avances reales en tres ejes: reducción de complejidad y sobrecarga, y mejoras en coherencia, velocidad y calidad
- Este sistema se aplica de forma general desde .NET 10 RTM y seguirá mejorando en futuras versiones
1 comentarios
Opiniones de Hacker News
De verdad admiro al equipo de .NET
Publican con frecuencia artículos técnicos profundos y su obsesión por la optimización de rendimiento es impresionante (por ejemplo, la evolución de Kestrel y Entity Framework)
ASP.NET es uno de los pocos proyectos grandes que sobrevivieron incluso a un cambio tan grande como el de Python 2→3
Antes dependía de funciones casi mágicas para sincronizar sesiones, pero ahora funciona de una forma completamente distinta
Se siente bien que una empresa valuada en 3 billones de dólares realmente quiera mejorar el stack que uso
Así que lo reemplacé con Dapper y un sistema de migraciones hecho por mí, y el tiempo de validación y seeding de la BD al arrancar bajó de 10 segundos a menos de 2 (en hardware modesto + SQLite)
Las consultas que generaba Entity tenían demasiados
joinmúltiples innecesariosÚltimamente me estoy pasando a un backend en Go simple, y .NET lo uso solo en otras soluciones
Frameworks como WPF tenían tantos problemas que hacían falta hacks de Win32
Por ejemplo, hasta .NET 9 por fin devuelve correctamente todas las interfaces de red. Los runtimes anteriores solo exponían las NIC activas
Todavía tengo proyectos que deben seguir soportando Windows 7
Incluso en proyectos nuevos todavía hay casos donde hay que usar .NET 4.8. Por ejemplo, al construir fórmulas de Excel aparece un problema de deadlock con async/await
Además, se rompió la integración con Windows, así que la misma llamada de red se autentica en 4.8 pero falla en Core
La ruptura de compatibilidad hacia atrás en muchísimas librerías hace que la migración no sea fácil
El rendimiento mejoró, pero en funcionalidad .NET Framework se siente fosilizado
Tardaron 15 años en agregar un serializador JSON a la biblioteca estándar, y tampoco hay soporte para formatos modernos de imagen como webp o heic
Visual Studio muestra mensajes de crash casi todos los días
Antes era un fan total de .NET, pero extraño el liderazgo de Anders
En un side project reciente he estado desarrollando un backend de API REST en C# con VSCode en macOS, y ya van 3 años desplegándolo en Linux
Uso SQLite, EFCore y Minimal API, y la experiencia es mucho más agradable que la del frontend (NextJS/React/MaterialUI, con más de 50 paquetes npm)
Personalmente es mi framework de API favorito
La segunda mejor opción sería una combinación de TS + Hono + Zod-OpenApi + SwaggerUI, aunque configurar el contexto de tipos es algo tedioso
Me pareció impresionante que la base para volver open source y multiplataforma a .NET haya sido el sistema de compilación de las distribuciones Linux
Por eso hacía falta un sistema de build que cumpliera sus requisitos, y al final la única dirección posible era integrarlo al modelo de distribuciones Linux
Ese modelo es simple, pero rinde menos. Un sistema de compilación distribuida con caché sería más rápido, pero no encaja con el flujo de trabajo de los mantenedores
Decidimos que optimizar la simplicidad era mejor para fomentar la participación de la comunidad
El objetivo es que la comunidad pueda encargarse directamente de compilar y distribuir para plataformas diversas como BSD, S390x y otras
La cantidad de pull requests y resultados positivos de los últimos 10 años es realmente sorprendente
No esperaba que el artículo de ingeniería de software que más me impresionó este año viniera de Microsoft
Me gustan las versiones recientes de .NET, pero pensaba que su solidez era producto de la casualidad
Sin embargo, este artículo muestra un esfuerzo sistemático por mejorar la calidad (incluyendo diagramas e incluso casos de uso de LLM)
Aunque en el futuro este tipo de inversión disminuya, sigue siendo un gran ejemplo de “cómo se deben hacer las cosas”
La gente que participó en este proyecto de verdad debió haber tenido una experiencia increíble
El artículo estuvo bien, pero creo que el equipo de .NET debería dejar Azure DevOps
El tiempo de espera en la cola es el mayor cuello de botella. Deberían usar servidores de build bare metal
El hardware de Mac se conecta y arranca rápido
Nosotros levantamos una VM limpia nueva para cada trabajo para garantizar compliance y estabilidad
Si mantuviéramos máquinas calientes ya preparadas, podríamos eliminar el tiempo de espera, pero el costo sería demasiado alto
Como no es realista mantener distintos SKU siempre en espera, terminamos haciendo un compromiso
Me pregunto por qué la Developer Division de Microsoft está al nivel más alto de la industria, mientras que el resto de la empresa se volvió símbolo de incompetencia y burocracia
Desde que Bill se fue, desapareció la cultura de mirarse a sí mismos críticamente
Creo que la raíz del problema es una forma de pensar centrada en la abstracción que intenta simplificar sistemas complejos
En vez de tratar de resolver todo en niveles altos, un enfoque de construir desde niveles bajos puede eliminar de raíz muchos más problemas
Al ver la frase “construimos 3 o 4 versiones principales al mes y decenas de bandas de SDK”, me pregunté por qué hay tantas variantes
Además, cada versión compila SDK/aspnet/runtime para múltiples plataformas como x64/arm32/arm64 y Linux/macOS/Windows
Antes de que Node se pusiera de moda, .NET era una opción sólida para construir backends (y su rendimiento también era mejor que el de Node)
Después de los recientes ataques a la cadena de suministro en el ecosistema de Node, ojalá muchos desarrolladores vuelvan a plataformas estables
El gran cambio fue la transición a .NET Core, pero eso fue hace casi 10 años
Actualizar el framework y las dependencias es un poco molesto, pero mucho más llevadero que actualizar proyectos de React
Gracias al ciclo corto de LTS, no es difícil mantenerse al día. En ciclos rápidos de desarrollo, este tipo de mantenimiento es algo normal
La realidad es que predominan Node.js, Java y el low-code (iPaaS)
Aun así, a veces surgen oportunidades de proponer addons en C++ gracias a problemas de rendimiento