2 puntos por GN⁺ 2025-10-05 | 1 comentarios | Compartir por WhatsApp
  • Con el lanzamiento de Zig 0.15.1, la velocidad de compilación mejoró notablemente frente a la versión anterior
  • En el proyecto Ghostty, al medir los tiempos reales de build, se observó en general una reducción en el tiempo de ejecución del proceso
  • Aunque todavía usa LLVM en parte, hay grandes expectativas de mejoras adicionales de velocidad cuando se aplique por completo su backend propio
  • La compilación incremental (incremental compilation) aún no está implementada por completo, pero ya se notan ventajas de rendimiento incluso en builds parciales
  • Es muy probable que en adelante se haga realidad un entorno de build más rápido y una mejor experiencia de desarrollo

Resumen

Partiendo de la frase de Andrew Kelley, "el compilador es tan lento que genera bugs", Zig ha llevado durante años diversos esfuerzos de mejora estructural con el objetivo de lograr tiempos de compilación más rápidos

  • El equipo de Zig ha estado trabajando en eliminar LLVM, desarrollar su propio backend de generación de código, construir un linker propio y, en última instancia, hacer realidad la compilación incremental
  • Los resultados de este desarrollo de largo plazo empezaron a hacerse visibles en la versión Zig 0.15.1, y se compartieron mediciones de los cambios en tiempo de build en un proyecto real (Ghostty)

Velocidad de compilación del Build Script

  • Zig 0.14: 7 segundos 167 ms
  • Zig 0.15: 1 segundo 702 ms

Es el tiempo de build del propio script build.zig, y representa un costo inicial que se paga cada vez en un entorno de compilación de código fuente nuevo

  • La frecuencia de recompilación del script de build se mantiene baja, pero impacta directamente en la experiencia del usuario cuando compila el proyecto por primera vez

Build completo del binario sin caché (Ghostty)

  • Zig 0.14: 41 segundos
  • Zig 0.15: 32 segundos

Es el tiempo total de build del binario, incluyendo también el tiempo de compilación del script de build

  • Con Zig 0.15 hay además una mejora adicional de alrededor de 2 segundos, y la diferencia inicial también es clara en tiempo real de reloj
  • El backend x86_64 propio todavía no se está aprovechando por completo, y en la mayoría de los casos se sigue usando LLVM
  • Se estima que, cuando Ghostty se compile por completo con el backend propio, el tiempo podría bajar de 25 segundos (aproximadamente la mitad frente a antes)

Build incremental (ejecutable de Ghostty)

  • Zig 0.14: 19 segundos
  • Zig 0.15: 16 segundos

Es el tiempo requerido para volver a compilar después de un cambio significativo de una línea (agregar una llamada de log en el código de emulación de terminal)

  • Se trata de un build parcial en una situación donde el script de build y el grafo de dependencias ya están en caché
  • Aunque la compilación incremental aún no está completamente implementada, la mejora de rendimiento ya se ve con claridad
  • Si se excluye LLVM en uso, hay posibilidad de reducirlo hasta alrededor de 12 segundos
  • Cuando se implemente una compilación incremental real, incluso se espera la posibilidad de builds en milisegundos

Build incremental (libghostty-vt)

  • Zig 0.14: 2 segundos 884 ms
  • Zig 0.15: 975 ms

Medición del tiempo para recompilar parcialmente solo libghostty-vt después de un cambio de una línea

  • libghostty-vt puede compilarse por completo con el backend x86_64 propio, por lo que las mejoras de Zig se reflejan directamente sin la influencia de LLVM
  • Incluso sin compilación incremental, lograr un tiempo de build por debajo de 1 segundo ya es un avance considerable
  • Mejora la eficiencia en el flujo de trabajo del desarrollador gracias a una experiencia de retroalimentación inmediata
  • Los backends x86_64 y aarch64 están volviéndose cada vez más estables, y existe la posibilidad de aplicarlos a todo Ghostty en los próximos meses

Estado actual de las mejoras en velocidad de build

  • El build de Ghostty usando Zig 0.15.1 es claramente más rápido en todos los puntos medidos
  • Aunque el backend propio y la compilación incremental aún no están terminados, los resultados actuales por sí solos ya son bastante impresionantes
  • Se espera que en los próximos 1 a 2 años lleguen mejoras de velocidad todavía más revolucionarias
  • Cada vez se siente más razonable haber elegido Zig desde la perspectiva de la velocidad de build

1 comentarios

 
GN⁺ 2025-10-05
Comentarios en Hacker News
  • Al graduarme de la preparatoria en 1995, recompilar "Borland Pascal versión Turbo Vision for DOS" en una Intel 486 era más o menos así de rápido; ahora por fin vuelvo a sentir velocidades de compilación realmente rápidas
    Turbo Vision era un framework de ventanas TUI, usado en el desarrollo de los IDE de Borland Pascal y C++
    Se podría decir que era como un JetBrains IDE en modo carácter de 10MB en lugar de 1000MB
    Wikipedia de Turbo Vision

  • LLVM es una especie de trampa
    El bootstrap es realmente rápido y obtienes gratis todo tipo de pases de optimización y soporte para múltiples plataformas, pero pierdes la capacidad de ajustar con detalle el rendimiento en la etapa final de optimización o de linking
    Creo que Cranelift pronto se activará en Rust
    Pero Rust tiene la posición que tiene hoy justamente porque al inicio eligió LLVM
    Go decidió desde hace mucho encargarse por sí mismo de la generación de código y el enlazado, sin delegarlo afuera, y ha aprovechado muchísimo esa decisión

    • Me cuesta estar de acuerdo con la idea de que LLVM sea una trampa, y Rust más bien es un buen ejemplo
      En la práctica, la parte que genera código con LLVM ocupa una porción muy pequeña del compilador, y si quieres reemplazarla puedes cambiar a codegen_cranelift o codegen_gcc
      La dependencia de intrínsecos SIMD de los vendors sí es un problema de lock-in, pero eso es un tema de la estructura del lenguaje
      Para la mayoría de los lenguajes, empezar con un backend de LLVM es razonable
      En lenguajes parecidos a C/C++, el pipeline base de LLVM ya optimiza bien, pero mientras más diferente sea el lenguaje, más sentido tiene escribir tu propio pipeline de optimización
      El caso de Go, que integró su propio backend desde el principio, sí parece exitoso, pero no es algo especialmente diferenciador, y construirlo tú mismo implica un costo de oportunidad bastante alto

    • Los compiladores de Go y Ocaml son realmente rápidos
      Construyeron bien sus propias librerías desde el inicio y ahora ya no tienen nada que perder en velocidad
      No quisiera trabajar en un entorno donde compilar tarde más de 1 minuto
      Ojalá cada proyecto tuviera un compilador exclusivo para dev, y que solo en el build final se usara algo pesado como llvm

    • Si un lenguaje basado en LLVM busca reemplazar a C++, seguirá dependiendo de C++
      Un lenguaje debe poder hacer bootstrap por sí mismo
      Al principio hay herramientas convenientes, pero solo sirven para ahorrar tiempo, no son indispensables
      Comparto por completo la decisión que tomó el equipo de Go

    • Ojalá Cranelift siga creciendo
      El LLVM actual está inundado de forks por vendor de CPU, y cada uno trae mejoras específicas del CPU amarradas a paquetes cerrados
      Si usas otro frontend de lenguaje o aparece un bug del compilador, la situación puede volverse muy dura

    • Se plantea la duda de cómo puede ser una trampa si los lenguajes pueden migrar libremente a otros backends

  • Si la velocidad de compilación estorba el desarrollo, surge la duda de por qué no hacer un intérprete
    La velocidad de ejecución y la velocidad de compilación son, por naturaleza, independientes
    Con un intérprete también sería fácil crear herramientas adicionales de desarrollo, como instrumentación de código o control del runtime
    Hay casos muy puntuales en los que debes depurar únicamente un binario RELEASE optimizado, pero en la mayoría de los casos basta con un intérprete o un build DEBUG

    • He oído que Rust se ordena como seguridad, rendimiento y usabilidad, mientras que Zig se ordena como rendimiento, usabilidad y seguridad
      Visto así, mejorar la velocidad de build sí resulta convincente, pero un intérprete es una alternativa más adecuada cuando la prioridad es la usabilidad

    • Me gusta el enfoque de Julia
      En un entorno totalmente interactivo, el intérprete en realidad compila el código y luego lo ejecuta de inmediato
      Lo mismo pasa en entornos Common Lisp como SBCL

    • Llevándolo al extremo, la velocidad de ejecución y la de compilación sí son independientes
      Entre ambos extremos hay una "zona de compromiso", donde se puede hacer el compilador más rápido sin perder rendimiento en el ejecutable

    • Se afirma que el sector de los videojuegos no es un caso especial

  • Hasta ahora, la mejor velocidad de compilador ha sido la de TCC (obra de Fabrice Bellard)
    Incluso sin multithreading ni optimizaciones complejas, es abrumadoramente rápido
    Para releases uso Clang, pero la generación de código de TCC tampoco está nada mal

    • Creo que Delphi ofrece una expresividad y seguridad mucho mayores, y aun así una velocidad de compilación muy alta

    • El compilador de Go también es bastante rápido

    • Pensaba que DMD era el "gold standard" por poder compilar tanto C como D

    • Ojalá TCC llegara a soportar C23

    • No existe una sola cosa que sea el "verdadero gold standard"
      En vlang una recompilación también termina en segundos, y el compilador de Go igualmente es muy rápido
      Además existen técnicas como el build caching para evitar por completo la recompilación, así que no es algo exclusivo de nadie

  • Al compilar una app con zig, me dejó muy satisfecho el incremental build
    Es posible compilar un solo binario estático usando varias librerías como SQLite y luau tan rápido como en Go
    Eso sí, el compilador self-hosted todavía tiene bastantes bugs
    Por ejemplo, SQLite requiere usar llvm, y el issue relacionado puede verse aquí

  • Me pregunto si Zig puede integrarse bien con sistemas de build como Bazel o Buck2
    El script de build de Zig es Turing-completo, así que me preocupa que en estos sistemas no sea fácil hacer caching ni automatización del build
    Es la misma razón por la que se prefieren más las librerías que pueden usarse en Rust sin build.rs
    También me pregunto si en las librerías de Zig hay mucho build personalizado

    • El script de build de Zig es completamente opcional
      Se pueden compilar o ejecutar archivos fuente individuales directamente, incluso sin build.zig
      Zig puede integrarse en cualquier workflow donde entren GCC o Clang
      Por cierto, Zig también funciona como reemplazo de compilador de C
      Artículo relacionado

    • Como ejemplo de integración entre Bazel y Zig, se presenta rules_zig
      El proyecto real ZML también lo aprovecha
      Proyecto ZML

  • Me pregunto cómo se comparan la compilación y la generación de código de Zig frente a TPDE
    Se dice que es entre 10 y 20 veces más rápido que LLVM -O0, pero parece que sí hay límites

  • La estrategia de Zig me parece audaz
    Pero todavía me pregunto si sigue siendo correcto usar el backend de LLVM
    LLVM es competitivo en velocidad de compilación y soporte de plataformas, pero en producción de código máquina óptimo no tiene rival

    • Solo en los builds Release se usa el backend de LLVM, y en los builds debug el enfoque self-hosted es el predeterminado para las plataformas compatibles
      Como los builds de depuración se repiten muchas veces durante las pruebas reales, este enfoque resulta más razonable

    • No comparto la obsesión con el rendimiento del compilador
      Al final es un trade-off entre pases de optimización (inlining, eliminación de código muerto, etc.) y tiempo de compilación
      Un compilador sin optimizaciones solo se volverá linealmente más rápido; si quieres ir más allá, el costo en tiempo inevitablemente aumenta

    • La "excelente salida en ensamblador" en realidad no es un tema tan importante
      Según la ley de Proebsting, el avance de la tecnología de compiladores es mucho más lento que el aumento del rendimiento del hardware
      La conclusión es que con optimizaciones simples y rápidas ya se obtiene algo suficientemente práctico
      LLVM tampoco ofrece optimización absoluta y, al compararlo con la velocidad de compilación, enseguida choca con límites

  • Al crear una librería Java que envuelve una librería C con JNI, compilar librerías dinámicas para cada plataforma es demasiado engorroso, así que estoy considerando usar zig para builds multiplataforma

    • Si solo es un shim simple, en Java moderno probablemente sea mejor usar Panama y jextract

    • Zig incluye headers, código fuente de libc y su propio LLVM, y la compilación cruzada es realmente fácil
      De verdad al punto de no tener que preocuparte por casi nada

  • Se preguntan por qué Ghostty todavía no puede compilarse con el backend self-hosted x86_64

    • El compilador de Zig se cae por un bug
      Todavía es una tecnología nueva y compleja, pero pronto se resolverá

    • La mayoría de los usuarios de Ghostty están en plataformas aarch64