- Distribuir una herramienta como un binario estático independiente permite que el usuario la use de inmediato sin instalar un entorno de desarrollo ni una toolchain aparte
- El proceso de compilación funciona como una capa adicional de seguridad que reduce la posibilidad de distribuir código defectuoso
- Las herramientas basadas en lenguajes interpretados implican una gran carga de mantenimiento, como instalación de dependencias, desperdicio de espacio en disco y reinstalaciones repetitivas al actualizar
- Cuantas más dependencias haya, mayor será la superficie de ataque y la exposición a vulnerabilidades de seguridad, lo que facilita riesgos de hackeo y problemas de mantenimiento
- Los binarios estáticos basados en lenguajes compilados no se ven afectados por cambios en el entorno externo, por lo que garantizan una usabilidad estable incluso después de la distribución
Ventajas de distribuir binarios estáticos independientes
Uso inmediato sin instalación
- Como en el caso de Open AI, que reconstruyó Codex en Rust y abandonó TypeScript, si distribuyes un binario único escrito en un lenguaje compilado, el usuario puede ejecutarlo de inmediato sin instalar toolchains adicionales
- La mayor ventaja no es la velocidad ni la eficiencia, sino poder usar la herramienta de inmediato, sin instalación
El compilador como capa adicional de seguridad
- Las verificaciones en la etapa de compilación reducen la posibilidad de distribuir código defectuoso
- Por ejemplo, Google Cloud CLI, basado en Python, fue distribuido varias veces en un estado no ejecutable
- Si incluso los equipos grandes tienen dificultades para evitar estos problemas, para los equipos pequeños es todavía más difícil distribuir de forma estable herramientas basadas en lenguajes interpretados
No se necesitan dependencias de toolchain
- Las herramientas basadas en lenguajes compilados solo requieren distribuir un binario único, mientras que las herramientas en lenguajes interpretados como Python, Ruby o TypeScript necesariamente requieren su entorno de desarrollo correspondiente
- Como ocurre con
mdl (markdown linter), escrito en Ruby, hace falta reinstalarlo cada vez que se actualiza el entorno de desarrollo (Ruby)
- Al usar
markdownlint, basado en JavaScript, es necesario instalar npm y más de 44 dependencias
El problema del desperdicio de espacio en disco
aider, un popular asistente de programación FOSS, está escrito en Python, y al instalarlo con Homebrew se instalan además 51 paquetes
- El uso real de disco aumenta en más de 3GiB, una cifra mayor que el tamaño de la mayoría de las distribuciones Linux
- En cambio, el gestor de paquetes
uv, escrito en Rust, puede instalarse con un binario único de 35MiB, sin necesidad de Rust ni de rustup
Aumento de vulnerabilidades de seguridad
- A medida que aumentan las dependencias de una herramienta, también crece la superficie de ataque y la posibilidad de exposición a vulnerabilidades de seguridad
- El paquete Codex de OpenAI tiene 24 dependencias directas y 184 indirectas
- Aunque OpenAI audite todas las dependencias, como las versiones no están fijadas, futuras actualizaciones podrían provocar problemas como vulnerabilidades, paquetes maliciosos o fallas en la ejecución
Facilidad de mantenimiento
- Las herramientas basadas en lenguajes interpretados como JavaScript, TypeScript o Python dejan de funcionar si se elimina una dependencia
- Como en el incidente de
left-pad, la eliminación de un solo paquete puede paralizar servicios y herramientas a gran escala
- Como los lenguajes compilados solo necesitan dependencias en el momento de la compilación, la herramienta puede seguir funcionando correctamente incluso si luego desaparece un repositorio externo
La experiencia del autor
- En el pasado creó herramientas en Python, como
adb-enhanced, pero después liberó como open source varias herramientas en Go, como gabo y wp2hugo
- Ya no considera desarrollar herramientas independientes con Python, TypeScript u otros lenguajes similares
- Recomienda escribirlas en lenguajes que permitan distribuir binarios enlazados estáticamente (Rust, Go, C++, etc.)
Conclusión
- Las herramientas independientes deben desarrollarse con lenguajes compilados como Rust, Go o C++
- Deben distribuirse en forma de binarios estáticos con la mínima cantidad posible de dependencias externas
3 comentarios
No puedo evitar identificarme bastante con el problema del
desperdicio de espacio en disco...Opero AKS, y cada vez que veo una app de Python con una imagen de contenedor que supera 1 GB, me duele la cabeza.
Por ahora simplemente tomo prestado el Dockerfile, vuelvo a reducir yo mismo el tamaño y lo subo; si no logro bajarlo de 500 MB, simplemente me rindo jaja
Hay paquetes cuyas dependencias de
pytorch+cudasolo difieren en la versión... es todo un espectáculo.Aunque casi no hacen nada, por cada pequeño daemon se terminan instalando cerca de 2 GB de dependencias..
Si es un runtime de CPU que se usa solo para inferencia simple, la cosa está un poco mejor, pero con los servicios de LLM que se piden hoy en día, tanto el tráfico como la capacidad siguen creciendo, así que dan ganas de maldecir cuando haces el cálculo de costos jajaja