- Cuando las fugas y los fallos persistieron en Zig, que no ofrece seguridad de memoria, Bun trasladó 535,496 líneas de código a Rust con 64 agentes de IA, reduciendo a 11 días un trabajo que habría tomado entre 1 y 2 años
- El punto de partida del éxito fue un
PORTING.mdde 600 líneas; el proceso siguió, en orden, conversión paralela archivo por archivo, dos revisiones adversariales, corrección de errores de compilación, pruebas locales y aprobación de CI - Para generar 6,500 commits se usaron, según precios de API, 165,000 dólares, 5,900 millones de tokens de entrada sin caché, 690 millones de salida y 72,000 millones de lecturas de tokens de entrada en caché
- Estiman que, si se hubiera hecho manualmente, 3 ingenieros que conocieran bien la base de código habrían tenido que detener durante cerca de un año las mejoras del producto, las correcciones de bugs y seguridad, y el desarrollo de nuevas funciones, por lo que la reescritura en sí habría sido difícil de justificar
- Para repetir el mismo enfoque se necesita un ingeniero que entienda profundamente la base de código, una suite de pruebas sólida cuyos resultados sean confiables y la voluntad de asumir el costo en tokens aunque el éxito sea incierto
Por qué Bun eligió reescribirse en Rust
- Bun es un proyecto de producción complejo que ofrece múltiples funciones más allá de ser un runtime de JavaScript
- Transformación, bundling y minificación de JavaScript, TypeScript y CSS
- Test runner y administrador de paquetes compatible con npm
- Resolución de módulos, cliente WebSocket, implementación de Node.js y varios módulos
- Tiene 22 millones de descargas mensuales; Claude Code y OpenCode dependen de él, y Vercel, Railway y DigitalOcean lo soportan directamente
- Zig no es un lenguaje con seguridad de memoria, por lo que incluso en versiones recientes de Bun seguían ocurriendo fugas de memoria, crashes por problemas de memoria y escrituras fuera del rango del heap
- El equipo de Bun parcheó el compilador de Zig e introdujo pruebas end-to-end de fugas de memoria, pero no logró eliminar el problema
- Al manejar conjuntamente la vida útil de valores con garbage collection y valores gestionados manualmente, aparecían pequeñas fugas y fallos intermitentes
- En cada asignación de memoria había que revisar dónde se liberaba, si había dobles liberaciones, el manejo de excepciones de JavaScript y la visibilidad de punteros para el escáner conservador de la pila
- En Rust seguro, los use-after-free y double-free se convierten en errores de compilación, y las liberaciones omitidas en rutas de error pueden manejarse con limpieza automática basada en
Drop - También evaluaron introducir en el código de Bun punteros inteligentes al estilo Rust, pero habrían sido menos usables que Rust y no ofrecían las mismas garantías
Por qué los proyectos de reescritura tradicionales tardan tanto
- Durante una reescritura, la base de código original sigue recibiendo funciones, por lo que la fecha de finalización tiende a retrasarse una y otra vez
- Un trabajo estimado en 9 meses puede seguir necesitando unos 6 meses más al cabo de esos 9 meses
- Incluso después de 15 meses, pueden quedar varios meses de trabajo para ponerse al día con las nuevas funciones
- Con suerte, tras congelar funcionalidades durante 2 meses, puede terminar alrededor de 18 meses después, y una estimación inicial de 9 meses puede extenderse a más de 2 años
- El código Zig de Bun, sin contar comentarios, tiene 535,496 líneas, por lo que estimaron que un equipo pequeño de ingenieros necesitaría cerca de un año para trasladarlo a otro lenguaje
- Como pasar un año sin mejoras visibles para los usuarios no era una opción realista, decidieron probar si Fable podía validar en menos de una semana la posibilidad de portar a Rust
Diseño y validación previos al port
- En la primera etapa conversaron con Claude durante unas 3 horas sobre cómo mapear patrones de Zig a equivalentes cercanos en Rust, y lo resumieron en un
PORTING.mdde 600 líneas - La guía de port incluía restricciones concretas para preservar la estructura de ejecución existente de Bun
- No usar
tokio,rayon,hyper,async-traitnifutures - Prohibir módulos que acceden a I/O, como
std::fs,std::netystd::process - Como Bun posee su propio event loop y sus llamadas al sistema, usar callbacks y máquinas de estado como en el Zig existente, en lugar de
async fn - Si aparece un conflicto con el borrow checker, guardar los valores escalares necesarios en variables locales, finalizar el préstamo y luego volver a pedir prestado
- Prohibir el uso de punteros crudos para evitar el borrow checker y dejar notas de port en los lugares donde se cambió la estructura
- No usar
- De los 1,448 archivos totales, primero reescribieron 3 archivos, y luego Claude los revisó adversarialmente dos veces en sesiones separadas del trabajo de cambios
Trabajo paralelo de 64 agentes de IA
- Dividieron el trabajo para que los archivos pudieran procesarse de forma independiente y ejecutaron 64 agentes de IA en paralelo
- Al principio, varios agentes tocaban el mismo estado del repositorio y se producían conflictos
- Un agente ejecutaba
git stashy luego otro ejecutabagit stash popygit reset HEAD --hard - Asignar un worktree separado a cada agente agotaba el espacio en disco debido al tamaño del repositorio de Bun, y además seguía existiendo la restricción de compilar los cambios en conjunto al final
- Un agente ejecutaba
- Ajustaron el workflow para prohibir comandos de Git como
git stashygit reset, salvo el comando para commitear inmediatamente un archivo específico, y también impidieron el uso decargoy de comandos de ejecución larga - Finalmente dividieron el trabajo en 4 worktrees, con 16 instancias de Claude en cada uno para commitear y hacer push de los archivos
- En dos días, los agentes trasladaron 535,496 líneas de código Zig, y cada commit pasó por dos revisiones adversariales antes de incorporarse
Corrección de errores de compilación y pruebas
- La conversión inicial terminó, pero el código no compilaba, así que Claude corrigió errores por crate, la unidad superior de compilación de Rust
- El título de la etapa menciona unos 1,600 errores de compilación, pero la cita indica que, al resolver dependencias circulares, aparecieron alrededor de 16,000 errores
- El proceso de corrección de errores también se paralelizó
- Ejecutar
cargo checken cada crate - Agrupar la salida por archivo y guardar archivos de errores
- Corregir todos los errores de compilación de ese crate
- Dos revisores adversariales verifican los cambios
- Un agente encargado de correcciones incorpora los resultados de la revisión
- Ejecutar
- Los agentes corrigieron errores de compilación sin intervención humana desde medianoche hasta las 11:30 a. m.
- Después dedicaron unos dos días más a lograr que la gran suite de pruebas se ejecutara localmente sin errores de compilación, y varios días adicionales a corregir pruebas fallidas hasta pasar CI
- Tras pasar todas las pruebas y verificar el funcionamiento, fusionaron los cambios; desde la planificación hasta la finalización tomaron 11 días en total
- Un port de unas 550,000 líneas de código
- 6,500 commits
- Uso de 64 agentes
Costos y resultado frente al trabajo manual
- Según los precios de la API de Fable, el costo total de la reescritura fue de 165,000 dólares
- 5,900 millones de tokens de entrada sin caché
- 690 millones de tokens de salida
- 72,000 millones de lecturas de tokens de entrada en caché
- Como Anthropic vende tokens de API con margen, el costo interno real es menor
- El costo de API es similar al salario base anual de un ingeniero de software empresarial de nivel medio en EE. UU., pero evalúan que sería imposible que un ingeniero con ese mismo salario lograra el mismo resultado en 11 días
- También coincide con la evaluación de Mitchell Hashimoto de que Fable destaca especialmente en trabajos difíciles y enfocados con una función de recompensa clara
- Estiman que, manualmente, habrían necesitado durante cerca de un año a 3 ingenieros que conocieran por completo la base de código
- Durante ese tiempo habría sido difícil mejorar la compatibilidad con Node.js, corregir bugs y problemas de seguridad, e implementar nuevas funciones
- La alternativa realista habría sido no reescribir y seguir corrigiendo los bugs de memoria existentes
Condiciones para aplicarlo a otros proyectos
- Si la IA reduce una reescritura o migración de un año a algo del orden de una semana, se vuelven viables proyectos que antes eran difíciles de considerar
- Para reutilizar el flujo de trabajo de Bun se necesitan tres condiciones
- Un ingeniero que conozca muy bien la base de código y tenga una fuerte voluntad de trabajar en ello
- Una suite de pruebas lo suficientemente sólida como para confiar en que pasar las pruebas respalda el funcionamiento real
- La disposición a invertir un costo considerable en tokens aun sin saber de antemano si tendrá éxito
- Los trabajos repetitivos como migraciones de código son relativamente adecuados para los LLM, así que si hay buenas pruebas y un ingeniero que pueda estructurar el problema, la probabilidad de éxito es alta
- No todos los proyectos necesitan 165,000 dólares
- En proyectos más simples, el costo puede ser menor
- Se puede usar el modelo más caro para la planificación de alto nivel y modelos más baratos para la codificación y la revisión
- Las migraciones basadas en IA están acelerándose, pero esta velocidad solo puede alcanzarse en proyectos bien ingenierizados como Bun
Aún no hay comentarios.