2 puntos por GN⁺ 2025-09-12 | 1 comentarios | Compartir por WhatsApp
  • La instalación de paquetes de Bun funciona a una velocidad muy superior en comparación con los gestores de paquetes existentes
  • La clave de su rapidez está en un enfoque desde la programación de sistemas y en la minimización de llamadas al sistema
  • Ofrece mejoras de rendimiento mediante estrategias detalladas como código nativo basado en Zig, uso de caché binaria y optimizaciones por sistema operativo
  • Incluso en el proceso de descompresión de tarballs y copia de archivos, adopta métodos de alto rendimiento que aprovechan las características del hardware
  • Mediante la optimización de estructuras de datos como el grafo de dependencias y el lockfile, mejora la eficiencia de la caché de CPU y la accesibilidad a la memoria

Por qué Bun Install es rápido

  • bun install de Bun ofrece, en promedio, un rendimiento de instalación de paquetes 7 veces más rápido que npm, 4 veces más rápido que pnpm y 17 veces más rápido que yarn
  • Esto no se debe solo a un benchmark, sino a que el problema de instalar paquetes fue abordado desde la perspectiva de la programación de sistemas y no desde JavaScript
  • Aplica agresivamente optimizaciones de rendimiento en múltiples capas, como minimización de llamadas al sistema, caché binaria de manifiestos, optimización de extracción de tarballs y copia de archivos nativa del sistema operativo

Límites de Node.js y de la arquitectura de los gestores de paquetes

  • Desde el lanzamiento de Node.js en 2009, el modelo de IO asíncrono basado en event loop y thread pool también se trasladó a los gestores de paquetes
  • En ese momento, debido a las limitaciones del hardware de la época (discos lentos, red lenta), la estrategia de IO asíncrono y alta frecuencia de llamadas al sistema era razonable
  • Sin embargo, en los sistemas modernos ya son comunes los SSD NVMe, redes rápidas y CPUs de alto rendimiento, y el verdadero cuello de botella ya no es el IO, sino el overhead de las llamadas al sistema

El costo de las llamadas al sistema y del cambio de modo

  • Cuando un programa solicita una operación como leer un archivo, debe cambiar de user mode a kernel mode, y este proceso consume costosos ciclos de CPU (1000~1500 cycles)
  • La instalación de paquetes requiere por naturaleza decenas de miles o incluso cientos de miles de llamadas al sistema, por lo que solo el costo de esos cambios puede consumir varios segundos de tiempo de CPU
  • Por ejemplo, al instalar React y sus dependencias, npm usa alrededor de 1 millón de llamadas al sistema, yarn 4 millones, pnpm 500 mil y bun 160 mil

Diferencias de enfoque entre los gestores de paquetes existentes y Bun

  • npm, pnpm y yarn están todos basados en Node.js, por lo que JavaScript debe ejecutarse a través de varias capas de abstracción (libuv, event loop, thread pool, intermediación de llamadas al sistema)
  • En este proceso se acumulan conversiones de argumentos, colas del worker pool, bifurcaciones de tareas del event loop y llamadas al sistema futex (sincronización de locks), lo que termina haciendo que la gestión de llamadas al sistema sea más lenta que el propio IO
  • Un gestor de paquetes hecho con Node.js tiene dificultades para alcanzar un rendimiento cercano al nativo debido a estas limitaciones estructurales

Bun: un motor de instalación nativo implementado en Zig

  • Bun, implementado en Zig, invoca directamente las llamadas al sistema, omitiendo por completo el motor de JavaScript y las capas de abstracción
  • Por ejemplo, la lectura de archivos ejecuta directamente la llamada al sistema openat() desde código Zig y devuelve los datos de inmediato
  • Por eso, el proceso de leer decenas de miles de archivos funciona a altísima velocidad sin pasar por thread pools, event loops ni transformaciones de datos adicionales
  • Según benchmarks, Bun puede leer 146,057 package.json por segundo, mientras que Node.js es más de 2 veces más lento, en el rango de 60 mil

Gestión de dependencias y optimización de DNS

  • Al ejecutar bun install, Bun dispara el análisis de dependencias y el DNS prefetch de manera asíncrona al mismo tiempo
  • Por ejemplo, en macOS usa la API async DNS no oficial de Apple (getaddrinfo_async_start()), lo que permite procesar trabajo de red en paralelo sin bloquear threads
  • Los gestores de paquetes existentes, al basarse en el thread pool de libuv, terminan ejecutando internamente código bloqueante y desperdiciando recursos

Caché binaria de manifiestos de paquetes

  • npm y otros almacenan en caché los manifiestos como JSON, pero Bun los parsea una vez y luego guarda el resultado convertido en binario (archivo .npm)
  • Esto minimiza la duplicación de strings y el overhead de parsing, y en memoria real permite acceder a los valores directamente con cálculos de offsets (sin crear nuevos objetos, sin parsing y sin garbage collection)
  • Con los headers ETag e If-None-Match puede verificar solo los cambios y validar actualidad sin parsear datos innecesarios
  • En benchmarks, la instalación desde caché de Bun es incluso más rápida que una instalación fresh de npm

Rendimiento en el procesamiento de tarballs (archivos comprimidos)

  • Los gestores de paquetes normales reciben el tarball como stream, y cuando falta memoria de buffer se producen continuamente reasignaciones, copias y redimensionamientos
  • Bun recibe el tarball completo antes de descomprimirlo y usa los últimos 4 bytes del gzip para conocer de antemano el tamaño descomprimido, por lo que solo asigna memoria una vez
  • Aprovecha libdeflate y otras técnicas para descompresión rápida, eliminando copias duplicadas innecesarias y cambios de tamaño

Optimización del grafo de dependencias y de las estructuras de datos

  • Los gestores de paquetes existentes construyen árboles de dependencias basados en objetos y punteros de JavaScript, lo que dispersa aleatoriamente la memoria y provoca frecuentes fallos de caché de CPU (problema de pointer chasing)
  • Bun aplica el patrón Structure of Arrays (SoA) para guardar todos los paquetes, strings y dependencias en grandes bloques continuos de memoria
    • Con acceso basado en offsets/longitudes, la CPU puede leer varios paquetes de una vez en unidades de cache line (estructura amigable con la caché)
    • El lockfile también se almacena, en lugar de JSON/YAML, de forma alineada con el patrón SoA, eliminando duplicación de strings y facilitando el acceso secuencial a memoria
  • También introdujo de forma experimental el formato binario de lockfile (bun.lockb), pero luego cambió a un formato de texto plano más legible debido al deterioro en la colaboración con Git

Optimización de copia de archivos por sistema operativo

macOS

  • Uso de clonefile: clona directorios completos en una sola llamada al sistema usando Copy-On-Write
  • Minimiza el uso duplicado de espacio en disco y maximiza la velocidad de instalación
  • Si clonefile falla, aplica un fallback escalonado: clonación por directorio y luego copyfile

Linux

  • Intenta primero hard links: crea una nueva referencia al archivo existente sin generar un archivo nuevo (sin mover datos en disco)
  • Si no se pueden usar hard links, en Btrfs/XFS aplica Copy-On-Write mediante ioctl_ficlone
  • Después hace fallback a copy_file_range, sendfile y finalmente a la copia tradicional con copyfile

Conclusión

  • Bun superó los límites tradicionales de rendimiento de los gestores de paquetes mediante minimización de llamadas al sistema, estructuras binarias, optimización por sistema operativo y mejoras en estructuras de datos
  • Gracias a ello, además de instalaciones ultrarrápidas, también ofrece mejoras en eficiencia de memoria y CPU
  • Puede aplicarse a proyectos sin reemplazar por completo el runtime frente a gestores basados en Node.js (manteniendo compatibilidad)
  • En bases de código grandes, ofrece la experiencia de reducir procesos de instalación que antes tardaban minutos a unos pocos milisegundos o segundos
  • Es un excelente caso de optimización a medida según el sistema, el hardware y el nivel del sistema operativo, con alto valor como referencia e investigación

1 comentarios

 
GN⁺ 2025-09-12
Opiniones en Hacker News
  • Intenté verificar la afirmación de que mi MacBook M4 Max estaría entre las 50 supercomputadoras del TOP500 de 2009
    Para entrar al TOP500 de 2009 se necesitaban más de 75 TFlop/s
    El M4 Max alcanza 18.4 TFlop/s en FP32, pero el TOP500 usa FP64 (LINPACK)
    Basándome en benchmarks del M2, FP64 rinde alrededor de 1/4 de FP32, así que se estiman unos 9 TFlop/s
    Con eso no entraría al TOP500 de 2009
    Ver la lista TOP500 de 2009

    • Si cada conexión hace varias operaciones de I/O al mismo tiempo, hay que multiplicarlo por miles de conexiones
      Escuché que un servidor pasa aproximadamente el 95% del tiempo esperando I/O, pero eso aplica a hilos individuales, no al servidor completo
      En servidores reales, el uso de CPU muchas veces sube hasta 70~80% (más allá de eso la tail latency empeora de golpe)
      Si en carga total la CPU usa 5%, entonces hay falta de procesos en paralelo o un problema de memoria
      Es un detalle técnico menor, pero ese tipo de errores puede afectar la credibilidad del post (lo digo como fan de Bun)

    • Esa conclusión se siente un poco como una alucinación generada por un LLM
      La parte final en particular da la impresión de haber salido de un LLM
      "Entendí que no es que los package managers evaluados en el benchmark estuvieran mal, sino que eran soluciones adecuadas para su época"
      "Se enfatiza que el enfoque de Bun no es tanto revolucionario, sino el resultado de observar con frialdad qué es lo que hoy provoca lentitud"
      "Que la instalación de paquetes sea 25 veces más rápida no es magia, sino un fenómeno natural de haber construido la herramienta para hardware moderno"

  • Me encantó que, a pesar de ser un tema complejo, estuviera explicado de forma simple y fácil de leer
    Sigue sorprendiéndome que todavía haya gente apasionada que rompa con el status quo y se atreva a enfrentar problemas difíciles
    Cada mes el hardware de computadoras mejora, pero el software se vuelve más lento, y eso se siente anormal
    Ojalá todos hiciéramos mejor el trabajo de escribir código eficiente

    • No sabía que bun estaba escrito en Zig
      Zig es un lenguaje bastante nuevo, así que resulta interesante verlo usarse de verdad en producción
  • Probé bun por primera vez y me dejó muy impresionado
    Gracias al servidor integrado y SQLite, basta con instalar bun y el desarrollo se vuelve mucho más cómodo
    Normalmente solo uso vanilla js y nunca me gustó mucho el ecosistema de node, así que siento que debí haber probado bun antes

    • He intentado usar Bun varias veces y la experiencia de uso me gustó mucho
      Me pareció mejor que Node
      Pero siempre termino topándome con un problema decisivo y vuelvo a Node
      Al principio el módulo crypto no era compatible con Nodejs (ahora ya está corregido), y después Playwright no funcionó en Bun

    • Hoy en día Node también ofrece servidor integrado y soporte para SQLite
      Si necesitas más funcionalidades, Hono también es una buena alternativa

  • No terminé de entender la parte del artículo donde explican que los hardlinks de Linux y clonefile de MacOS son equivalentes
    En el caso de los hardlinks, ¿si modificas una copia no cambiarían inesperadamente los archivos de todos los proyectos?

  • Me impresionó que, aunque la explicación era bastante compleja técnicamente, estaba escrita de una forma muy clara y amena

    • Lydia es muy buena para comunicar conceptos complejos de forma sencilla
      He visto la mayoría de sus trabajos y videos, y se nota que prepara todo con mucha profundidad
      Si tienes tiempo, recomiendo mucho sus artículos y su contenido en YouTube
      Últimamente parece que ha estado menos activa, probablemente por su trabajo actual
  • En la sección de Binary Manifest Caching, parece que falta el tiempo de benchmark de "npm (cached)"
    Solo aparecen bun, bun (cached) y npm, y además las estadísticas resumidas tampoco parecen cuadrar bien

  • Me gustó muchísimo el estilo de redacción de este post
    Parece un caso excelente para reaprovecharlo al explicar la importancia de io_uring
    Me pregunto si la actualización reciente de io en Zig v0.15 podría darle beneficios adicionales al rendimiento de Bun

  • Llevo más de un año esperando bun
    Pensé que 2025 sería el año en que bun se volvería masivo, pero sorprendentemente todavía no es tan popular
    Entre los 100 mil repositorios principales de GitHub, en los repos nuevos de 2025 npm se usa 35 veces más y pnpm 11 veces más
    Deno tampoco parece tan popular como uno imaginaría
    Me pregunto por qué será
    ¿Será porque es más difícil lograr compatibilidad en un runtime que en un package manager?
    Me gustaría escuchar opiniones de quienes probaron bun y decidieron no adoptarlo
    Estadísticas relacionadas
    Comentario relacionado en HN

    • He intentado varias veces querer tanto a Bun como a Deno, pero al final siempre me topo con un defecto crítico y ya no puedo seguir usándolos
      El problema más grande que tuve recientemente en Bun fue uno donde los streams se cerraban antes de tiempo
      Issue relacionado
      En Deno me encontré con un problema de fuga de memoria
      Issue relacionado
      Al final me da la impresión de que el ecosistema de Node va a incorporar primero las ventajas de Bun/Deno

    • Bun es un recién llegado compitiendo contra un producto open source ya validado y dominante (Node), con dinero fresco de venture capital detrás
      Tiene incentivos de lock-in y, al final, no es fundamentalmente tan distinto de Node
      No tiene una ventaja estratégica clara ni ofrece algo realmente nuevo que no pueda hacerse con Node
      No he visto casos de uso verdaderamente serios, solo usos ligeros

    • Viendo el issue tracker, parece que el lenguaje Zig no es muy seguro y por eso ocurren crashes con frecuencia
      Yo me voy a quedar en Node

    • A mí también me da curiosidad la opinión de otros
      En mi percepción, Node es un proyecto maduro, democrático y muy guiado por la comunidad
      También porque supo superar bien la crisis del fork de io.js
      En cambio, tanto bun como deno son proyectos financiados por VC, así que no se sienten tan democráticos ni impulsados por la comunidad

    • Soy un fan total de Bun
      Uso Bun en todos los proyectos donde puedo, y también para todo tipo de scripts one-off con Bun/TS
      Aun así, hay algunos issues, aunque pocos, que me preocupan y por eso todavía dudo en desplegarlo en producción
      Por ejemplo, cuando levanté un servidor web simple de Express en Docker, si lo corría con bun se quedaba congelado
      Si lo cambiaba solo a node, funcionaba normalmente
      Hace un año también tuve un problema de fuga de memoria con la combinación Bun + Prisma que terminaba tumbando el servidor (supongo que ya debe estar arreglado)
      Aun así, Bun me gusta tanto que incluso aceptando esas desventajas me ahorra tiempo de desarrollo en general
      La comodidad en transpilación, módulos, workspaces y demás es enorme
      También entiendo perfectamente que todavía no se haya masificado al nivel de npm

  • Leer este artículo fue un placer total
    Es un gran ejemplo de lo importantes que son en la práctica los principios de ciencias de la computación en el desarrollo de software
    Big O, localidad temporal/espacial, complejidad algorítmica, espacio de usuario/kernel, sistemas de archivos, copy-on-write, etc.
    En este tipo de desarrollo de paquetes de bajo nivel, todos los conceptos que se aprenden en un programa de CS se usan de verdad

    • En realidad esto se acerca más a ingeniería de software (SE) que a ciencias de la computación (CS)
      CS estudia la computación y la teoría (lenguajes de programación, algoritmos, criptografía, machine learning, etc.)
      SE aplica principios de ingeniería para construir software escalable y confiable
  • No me queda claro por qué sería mejor esperar a leer por completo el archivo comprimido antes de descomprimirlo
    Yo supondría que empezar a descomprimir antes de que termine la descarga daría más beneficio que el costo adicional de aumentar las copias en memoria