Cómo Dune llegó a ser un mejor sistema de build para OCaml
(blog.janestreet.com)- Jane Street creó Jenga a partir de su insatisfacción con OMake, pero tuvo poca adopción externa; Jbuilder, creado como capa de compatibilidad, terminó creciendo de forma inesperada hasta convertirse en una herramienta base para la comunidad OCaml
- El atractivo inicial de Jbuilder fue más su velocidad y portabilidad que sus funciones, y en los proyectos de Jane Street una compilación aproximadamente 5 veces más rápida que OCamlbuild impulsó su adopción
- Jbuilder evolucionó hasta convertirse en un sistema de build completo en colaboración con OCaml Labs y, tras una discusión comunitaria por un conflicto de nombre con un antiguo IDE Java de Borland, pasó a llamarse Dune
- Jane Street mantuvo Jenga y Dune en paralelo durante un tiempo, pero a medida que su base de código creció hasta 65 M de líneas de OCaml y 5 M de líneas de Python, la dificultad de la migración interna aumentó mucho
- Tras más de un año de trabajo intensivo, la base de código de Jane Street ahora se compila con Dune, y los builds con la caché mayormente llena son 2 a 3 veces más rápidos
Jenga nació de la insatisfacción con OMake
- Un sistema de build es una herramienta cotidiana para desarrolladores que crea programas ejecutables a partir de varios archivos fuente, y también se encarga de invocar compiladores y ejecutar pruebas
- Alrededor de 2012, Jane Street estaba insatisfecha con OMake, uno de los sistemas de build estándar de OCaml, y creó su propio sistema de build: Jenga
- Como Jenga funcionaba bien internamente, Jane Street decidió publicarlo pensando que la comunidad también podría aprovecharlo
- Esperaban que usuarios externos probaran Jenga y contribuyeran
- También pensaban que sería más fácil liberar como open source el código de Jane Street
- La adopción externa real no cumplió las expectativas
- No funcionaba en Windows
- Para adoptar Jenga, en la práctica había que aceptar toda la forma Jane Street de compilar OCaml
- Como el uso externo no crecía, Jane Street volvió a hacer privado Jenga, y el problema de compilar su código open source siguió pendiente
Jbuilder como capa de compatibilidad
- En 2016, Jane Street decidió crear Jbuilder, una herramienta simple y multiplataforma que permitiera a usuarios externos compilar su código sin adoptar todo Jenga
- La herramienta también buscaba reducir la carga de reescribir los builds para adaptarlos a OCamlbuild, que en ese momento estaba emergiendo como el nuevo estándar para compilar proyectos OCaml
- Jbuilder entendía los archivos
jbuildque Jenga usaba para la configuración de build, y ejecutaba los comandos de compilación necesarios en orden topológico - El Jbuilder inicial estaba lejos de ser un sistema de build en el sentido habitual
- No volvía a ejecutar solo los comandos cuyos inputs habían cambiado
- En cada ejecución, volvía a ejecutar todos los comandos
Cómo Jbuilder se convirtió en Dune
- Jbuilder fue pensado originalmente como una pequeña capa de compatibilidad, pero los usuarios empezaron a usarlo no solo para paquetes de Jane Street, sino también para compilar sus propios proyectos
- El principal factor que impulsó su adopción fue la velocidad
- En la compilación de proyectos de Jane Street era aproximadamente 5 veces más rápido que OCamlbuild
- Tenía buena portabilidad
- Su estructura era simple y fácil de modificar
- Jane Street empezó a colaborar con OCaml Labs, hoy Tarides, para convertir Jbuilder en un sistema de build más completo
- El nombre se volvió un problema aparte
- Ya existía JBuilder, el IDE Java de Borland
- Aunque ese sistema prácticamente había desaparecido hacía mucho tiempo, al consultar a los titulares de los derechos sobre la intención de usar el nombre, no obtuvieron autorización
- Tras una discusión en la comunidad, se eligió Dune como nuevo nombre
- La discusión relacionada se llevó a cabo en el hilo para proponer un nuevo nombre para Jbuilder
El costo de mantener dos sistemas de build en paralelo
- A medida que Dune se hizo más popular, Jane Street pasó a mantener y dar soporte al mismo tiempo a dos sistemas de build completos creados por ellos: Jenga y Dune
- Dune se consolidó como un sistema con una arquitectura rediseñada, buen rendimiento en la mayoría de los builds de usuarios, una adopción más amplia, mejores APIs y una mejor experiencia de usuario
- La pregunta de cuándo migrar internamente a Dune surgió de forma natural, pero el equipo de sistemas de build estaba ocupado simplemente siguiendo el ritmo de una base de código en crecimiento
- Cuando Dune comenzó en 2016, el código OCaml tenía 4 M de líneas
- Hoy hay 65 M de líneas de OCaml y 5 M de líneas de Python
- La migración a Dune implicaba una carga grande, por lo que no se inició de lleno, y solo se repetían estimaciones optimistas de que “podría ser posible en los próximos 6 a 12 meses”
- El año pasado, Jane Street amplió el equipo de sistemas de build a 5 ingenieros de tiempo completo y luego inició la migración largamente postergada
Dune reemplazó a Jenga dentro de Jane Street
- Una de las tareas más grandes fue hacer que Dune pudiera escalar para ajustarse a la enorme base de código de Jane Street
- Una de las razones por las que Dune era rápido fuera de Jane Street era que la mayoría de los usuarios compilaba proyectos mucho más pequeños que el repositorio de 70 M de líneas de Jane Street
- Jenga tampoco había estado detenido durante 10 años
- Jane Street había seguido mejorando la implementación de Jenga para acompañar el crecimiento de la base de código
- Jenga estaba considerablemente optimizado para los requisitos de un monorepo de gran escala
- Gran parte de ese trabajo de optimización debía trasladarse a Dune
- El trabajo de integración cotidiano tampoco fue menor
- El sistema de build se invoca desde varios flujos de trabajo
- Los tres editores Vim, Emacs y VSCode tenían integraciones personalizadas para Jenga
- Cada integración tuvo que migrarse a Dune una por una
- Tras más de un año de trabajo intensivo, la base de código de Jane Street ahora se compila con Dune
- En el momento de la transición, el rendimiento de Dune era, en general, igual o mejor que el de Jenga
- En algunos casos mostraba un rendimiento mucho mejor
- Cuando la mayoría de las tareas de build ya estaban en caché, el build era 2 a 3 veces más rápido
Próximas mejoras posibles sobre un único sistema
- Jane Street planea publicar como open source gran parte del trabajo de mejora de rendimiento de Dune, y algunas partes ya se publicaron
- Para evitar que vuelvan a existir dos sistemas —un fork de Dune para Jane Street y el Dune externo—, están prestando atención a enviar los cambios posibles upstream
- Dune se volvió una base más adecuada para crear nuevas funciones
- La base de código es más simple y más fácil de trabajar
- Pueden concentrarse en un solo sistema
- Las siguientes funciones también están más cerca
-
Builds distribuidos
- Builds superficiales, es decir, “builds without the bytes”
- Carga en caché del propio grafo de build
- El equipo de sistemas de build creció a 12 ingenieros de tiempo completo en Nueva York, Londres y Singapur, y también aumentó la velocidad de mejora de Dune
-
1 comentarios
Opiniones en Hacker News
Mensaje de crasheo de Dune:
https://github.com/ocaml/dune/issues/2767
En el podcast técnico Signals and Threads de Jane Street hubo un episodio de 2020 sobre sistemas de build, y lo recomiendo mucho
Los demás episodios también son buenos; recomiendo especialmente The Future of Programming, con Richard Eisenberg, y What is an Operating System?, con Anil Madhavapeddy
¥https://signalsandthreads.com/build-systems/
°https://signalsandthreads.com/future-of-programming/
§https://signalsandthreads.com/what-is-an-operating-system/
https://signalsandthreads.com/multicast-and-the-markets/
Es respetable que Jane Street haya demostrado que la programación funcional con tipos HM también puede estar lista para producción y ser muy rápida si se le dedica suficiente esfuerzo
Todavía a veces escucho que los lenguajes funcionales de estilo más académico no sirven en producción, pero OCaml muestra que sí es totalmente viable incluso con requisitos de alto rendimiento
https://mercury.com/
Es una excelente opción para crear programas de alta calidad con amplia interoperabilidad con sistemas existentes
Según una publicación de blog de hace unos años, también habían probado Roc, pero no sé si lo usan ahora
[0] https://blog.noredink.com
Cada vez que veo una publicación del blog de Janestreet, me río para mis adentros porque trabajar en finanzas en Jane parece más divertido y mejor pagado que el 90% de los llamados trabajos de la industria tecnológica
En los puestos tecnológicos del sector financiero hay muchísimos trabajos que no son ni tan interesantes ni tan bien pagados como una empresa tecnológica promedio, ni hablar de Jane Street
Mucho del trabajo en finanzas consiste en arreglar código Java de 20 años o encontrar nuevas formas de meter y sacar datos de archivos Excel para reportes personalizados
Además, escuché que entrar a JS es mucho más difícil que a Google/Meta
Yo también postulé hace tiempo y el entrevistador fue bastante desagradable; en entrevistas con big tech nunca me pasó eso, así que no me dejó una buena impresión
Aun así, lo valoro más que hacer que la gente haga clic en anuncios
Como en otras empresas, hay una mezcla de proyectos interesantes y tareas aburridas
Lo único peor que una base de código compleja es un sistema de build complejo. CMake es detestable
Es como: “¡aprende otro lenguaje nuevo para compilar este lenguaje!”
También hace algunas cosas bien, y parte de lo que hace mal es manejable
Si con un conjunto de archivos de configuración editables por humanos puedo obtener procedimientos de build para varias plataformas, puedo tolerar cierto nivel de dolor
El lenguaje de scripting espantoso lo frena, pero con suficiente motivación podría mejorar
Hace tiempo, después de Lisp, pasé varios años del lado de Haskell como mi primera experiencia funcional.
OCaml no me terminaba de llegar, y como tengo una forma rara de alergia a los punto y coma, Haskell me parecía mucho más agradable a la vista.
Pero hace poco probé Reason y me gustó mucho; de pronto todo lo relacionado con OCaml se volvió interesante.
https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...
https://ocaml.org/docs/toplevel-introduction#loading-librari...
https://reasonml.github.io/ se ve genial, como un OCaml con aire a JavaScript.
Supongo que cuando entiendes esa línea ya está bien, pero parece que, igual que con Lisp, hay que aprender a pensar con esa estructura. Aun así, una pantalla llena de código Haskell todavía me intimida.
De todos ellos, SML/NJ fue el más fácil de leer para mí.
Me da curiosidad si alguien ha usado las bibliotecas y herramientas OCaml open source de Jane Street en algún proyecto más o menos serio.
Por lo poco que vi, me dio la impresión de que han puesto mucho esfuerzo en crear un ecosistema y liberar código como open source, pero que no está “listo” para que lo use gente fuera de Jane Street.
Para encontrar algo hay que saber leer firmas de funciones con bastante soltura, pero fuera de eso no tengo quejas. Por ejemplo, las funciones para convertir todos los tipos básicos a s-expresiones y de vuelta, si sabes que existen y las planeas de antemano, te ahorran muchísimo tiempo.
También probé otras bibliotecas, y sus ppx de logging y pruebas unitarias son casi un estándar de facto en el mundo OCaml, en la medida en que algo así exista. También usé el formateador de código, un framework de pruebas y algunas implementaciones de estructuras de datos avanzadas.
A veces, como dicen otros comentarios, te encuentras con cosas que realmente no funcionan. Dependen de algo separado que no está documentado, o requieren una configuración secreta, cosas así. No es mala fe; si abres un issue y vuelves uno o dos años después, muchas veces ya funciona.
No es que no haya frustraciones, pero agradezco el enfoque de publicar todo en vez de gastar recursos en probar y pulir menos releases. La calidad del código suele ser muy alta y, aunque no logres hacerlo funcionar directamente, sirve como una implementación de ejemplo rigurosa y verificada.
Me parece que la API es mucho mejor que la stdlib estándar.
Me gusta Lean 4, pero no es fácil recibir ayuda de la IA. La tarea de hoy es digerir el manual de referencia para que entre bien en una ventana de contexto de 200K. Veremos si ayuda.
Me sorprende bastante que todavía tenga sentido desarrollar un sistema de build propio y migrar hacia él, en vez de adoptar una herramienta existente como buck2 o bazel.
No digo que sea fácil introducir herramientas de build avanzadas como esas, pero ¿comparado con hacer una propia? Me da curiosidad si hay algo especial que haga a dune muy distinto.
La primera release de Bazel fue en 2015, y Buck salió en 2013.
JS tiene algo de cultura NIH, pero no sé si eso influyó aquí. En esa época no había muchas buenas herramientas de build, y menos aún para una empresa con un stack tecnológico poco convencional.
En particular, entiendo que hay que poder ejecutar ocamldep de antemano o compilar dos veces; buck2 puede hacerlo, y Bazel, si no recuerdo mal, requiere hacks.
Son más o menos parecidos. En velocidad pura al invocar herramientas de build de OCaml, dune es más rápido; cuando hay que recompilar muchas cosas y se usa un sistema de build distribuido, buck2 gana.
El gran dolor es la integración con LSP. Como la única forma en que el servidor LSP puede conocer las dependencias de un archivo es mediante el build, tiene que estar estrechamente acoplado al sistema de build. En dune todo viene de forma limpia. Con buck2 también logramos conectarlo de alguna manera, pero no queda igual de bien.
Dune es, por lejos, el mejor nombre para un sistema de build; no hay nada que se le acerque.
Empezaron intentando crear un mejor sistema de build y “por casualidad” terminaron creando un mejor sistema de build; qué rara es la forma en que ocurren esas casualidades.