2 điểm bởi GN⁺ 2025-09-12 | 1 bình luận | Chia sẻ qua WhatsApp
  • Cài đặt gói của Bun hoạt động với tốc độ rất nhanh so với các trình quản lý gói hiện có
  • Cốt lõi của tốc độ cài đặt cao nằm ở cách tiếp cận theo góc nhìn lập trình hệ thốnggiảm thiểu system call
  • Hiệu năng được cải thiện nhờ áp dụng các chiến lược tinh chỉnh như lập trình native bằng ngôn ngữ Zig, sử dụng bộ nhớ đệm nhị phân và tối ưu hóa theo từng hệ điều hành
  • Ngay cả trong quá trình giải nén tarball và sao chép tệp, Bun cũng áp dụng các phương pháp hiệu năng cao tận dụng đặc tính phần cứng
  • Thông qua tối ưu hóa cấu trúc dữ liệu như đồ thị phụ thuộc và lockfile, Bun nâng cao hiệu quả cache CPU và khả năng truy cập bộ nhớ

Vì sao Bun Install nhanh

  • bun install của Bun trung bình mang lại hiệu năng cài đặt gói nhanh hơn npm 7 lần, pnpm 4 lần và yarn 17 lần
  • Đây không chỉ là khác biệt trong benchmark, mà còn đến từ việc tiếp cận bài toán cài đặt gói từ góc nhìn lập trình hệ thống thay vì JavaScript
  • Bun tích cực áp dụng tối ưu hiệu năng ở nhiều tầng như giảm số lượng system call, lưu cache nhị phân cho manifest, tối ưu giải nén tarball và sao chép tệp native theo hệ điều hành

Giới hạn của Node.js và kiến trúc trình quản lý gói

  • Từ sau khi Node.js ra mắt năm 2009, mô hình IO bất đồng bộ dựa trên event loop và thread pool cũng được lan sang các trình quản lý gói
  • Vào thời điểm đó, do hạn chế phần cứng như ổ đĩa chậm và mạng chậm, chiến lược IO bất đồng bộ với tần suất system call cao là hợp lý
  • Tuy nhiên, trên các hệ thống hiện đại, SSD NVMe, mạng nhanh và CPU hiệu năng cao đã trở nên phổ biến, và nút thắt thực sự không còn là IO mà là overhead của system call

Chi phí của system call và chuyển đổi chế độ

  • Khi chương trình yêu cầu thực hiện tác vụ như đọc tệp, nó phải chuyển từ user mode sang kernel mode, và quá trình này tiêu tốn một lượng chu kỳ CPU đắt đỏ (1000~1500 cycles)
  • Về bản chất, cài đặt gói cần tới hàng chục nghìn đến hàng trăm nghìn system call, nên chỉ riêng chi phí chuyển đổi tác vụ thực tế cũng có thể tiêu tốn vài giây thời gian CPU
  • Ví dụ, khi cài đặt React và các phụ thuộc, npm sử dụng khoảng 1 triệu system call, yarn 4 triệu, pnpm 500 nghìn, còn bun là 160 nghìn

Khác biệt trong cách tiếp cận giữa các trình quản lý gói hiện có và Bun

  • npm, pnpm và yarn đều dựa trên Node.js, nên JavaScript phải chạy qua nhiều lớp trừu tượng như libuv, event loop, thread pool và tầng trung gian của system call
  • Trong quá trình đó, việc chuyển đổi đối số, hàng đợi worker pool, phân nhánh công việc trong event loop và các system call futex (đồng bộ khóa) bị cộng dồn, khiến việc quản lý system call thậm chí còn chậm hơn cả IO
  • Các trình quản lý gói viết bằng Node.js khó đạt được hiệu năng tiệm cận native do các giới hạn mang tính cấu trúc này
Quảng cáo

Bun: engine cài đặt native được triển khai bằng Zig

  • Bun gọi trực tiếp system call bằng ngôn ngữ Zig, bỏ qua hoàn toàn JavaScript engine và các lớp trừu tượng
  • Ví dụ, việc đọc tệp được thực hiện bằng cách gọi trực tiếp system call openat() trong mã Zig để trả về dữ liệu ngay lập tức
  • Vì vậy, quá trình đọc hàng chục nghìn tệp có thể chạy cực nhanh mà không cần thread pool, event loop hay bước chuyển đổi dữ liệu riêng biệt
  • Theo benchmark, Bun có thể đọc 146.057 file package.json mỗi giây, trong khi Node.js chậm hơn hơn 2 lần ở mức khoảng 60 nghìn file

Tối ưu quản lý phụ thuộc và DNS

  • Khi chạy bun install, Bun sẽ phân tích phụ thuộc đồng thời kích hoạt DNS prefetch một cách bất đồng bộ
  • Chẳng hạn trên macOS, Bun sử dụng API DNS bất đồng bộ không chính thức của Apple (getaddrinfo_async_start()), hỗ trợ xử lý đồng thời tác vụ mạng mà không chặn thread
  • Các trình quản lý gói hiện có dựa trên thread pool của libuv, nên trên thực tế vẫn chạy mã blocking bên trong và gây lãng phí tài nguyên

Lưu cache nhị phân cho manifest gói

  • npm và các công cụ tương tự lưu cache manifest ở dạng JSON, còn Bun sau khi parse một lần sẽ chuyển kết quả đó sang dạng nhị phân (.npm) để lưu trữ
  • Giảm thiểu trùng lặp chuỗi và overhead parse, đồng thời trong bộ nhớ thực tế có thể truy cập giá trị ngay bằng cách tính offset mà không cần tạo object mới, parse lại hay garbage collection
  • Bun dùng header ETag và If-None-Match để chỉ kiểm tra phần thay đổi, giúp xác minh tính cập nhật mà không cần parse dữ liệu không cần thiết
  • Theo benchmark, cài đặt từ cache của Bun còn nhanh hơn cả fresh install của npm

Hiệu năng xử lý tarball (tệp nén)

  • Các trình quản lý gói thông thường nhận tarball dưới dạng stream, và mỗi khi bộ nhớ đệm không đủ sẽ liên tục phát sinh cấp phát lại, sao chép và thay đổi kích thước
  • Bun nhận toàn bộ tarball rồi mới giải nén, đồng thời dùng 4 byte cuối của gzip để biết trước kích thước sau giải nén → chỉ cấp phát bộ nhớ đúng một lần
  • Bun cũng tận dụng libdeflate để giải nén nhanh, đồng thời loại bỏ hoàn toàn việc sao chép dư thừa và thay đổi kích thước không cần thiết
Quảng cáo

Tối ưu đồ thị phụ thuộc và cấu trúc dữ liệu

  • Các trình quản lý gói hiện có tạo cây phụ thuộc dựa trên object/pointer JavaScript, dẫn tới bộ nhớ bị phân tán ngẫu nhiên và thường xuyên xảy ra cache miss của CPU (vấn đề pointer chasing)
  • Bun áp dụng mô hình Structure of Arrays (SoA), lưu toàn bộ package, chuỗi và phụ thuộc trong các khối bộ nhớ liên tục lớn
    • Truy cập dựa trên offset/độ dài cho phép CPU đọc nhiều package cùng lúc theo đơn vị cache line (cấu trúc thân thiện với cache)
    • Lockfile cũng được lưu theo mô hình SoA thay vì JSON/YAML, giúp loại bỏ trùng lặp chuỗi và thuận lợi cho truy cập bộ nhớ tuần tự
  • Bun từng thử nghiệm định dạng lockfile nhị phân (bun.lockb), nhưng sau đó chuyển sang định dạng văn bản dễ đọc hơn do làm giảm khả năng cộng tác với Git

Tối ưu sao chép tệp theo từng hệ điều hành

macOS

  • Dùng clonefile: sao chép toàn bộ thư mục bằng cơ chế Copy-On-Write chỉ với một system call
  • Giảm tối đa việc dùng trùng lặp dung lượng đĩa và tăng tốc độ cài đặt lên mức cao nhất
  • Nếu clonefile thất bại, Bun sẽ fallback theo từng bước từ cloning theo từng thư mục sang copyfile

Linux

  • Ưu tiên thử hard link: không tạo tệp mới mà chỉ tạo tham chiếu mới tới tệp hiện có (không cần di chuyển dữ liệu trên đĩa)
  • Nếu không thể dùng hard link, trên Btrfs/XFS Bun sẽ áp dụng Copy-On-Write bằng ioctl_ficlone
  • Sau đó mới fallback lần lượt sang copy_file_range, sendfile, và cuối cùng là cách copyfile thông thường

Tổng kết

  • Bun đã vượt qua giới hạn hiệu năng truyền thống của trình quản lý gói nhờ giảm thiểu system call, cấu trúc nhị phân, tối ưu theo hệ điều hành và cải tiến cấu trúc dữ liệu
  • Nhờ đó, Bun không chỉ cài đặt cực nhanh mà còn cải thiện cả hiệu quả bộ nhớ và CPU
  • So với các trình quản lý dựa trên Node.js hiện có, Bun có thể được áp dụng vào dự án mà không cần thay runtime riêng biệt (vẫn giữ khả năng tương thích)
  • Trong các codebase lớn ngoài thực tế, Bun mang lại trải nghiệm rút ngắn quá trình cài đặt từ vài phút xuống còn vài mili giây đến vài giây
  • Đây là một ví dụ xuất sắc về tối ưu hóa được thiết kế sát với cấp độ hệ thống, phần cứng và hệ điều hành, rất đáng để nghiên cứu và tham khảo

1 bình luận

 
GN⁺ 2025-09-12
Ý kiến trên Hacker News
  • Tôi đã thử kiểm chứng nhận định rằng chiếc MacBook M4 Max tôi đang dùng lẽ ra đã có thể lọt vào top 50 siêu máy tính TOP500 nếu tính theo tiêu chuẩn năm 2009
    Để vào được TOP500 năm 2009 thì cần hiệu năng trên 75 TFlop/s
    M4 Max đạt 18.4 TFlop/s ở FP32, nhưng TOP500 dùng FP64 (LINPACK)
    Dựa trên benchmark của M2, FP64 chỉ bằng khoảng 1/4 FP32, nên ước tính vào khoảng 9 TFlop/s
    Mức đó không đủ để lọt vào TOP500 năm 2009
    Tham khảo danh sách TOP500 năm 2009

    • Nếu mỗi kết nối thực hiện nhiều tác vụ I/O đồng thời thì phải nhân lên với hàng nghìn kết nối
      Tôi từng nghe rằng máy chủ dành khoảng 95% tổng thời gian để chờ I/O, nhưng trên thực tế điều đó áp dụng cho từng thread chứ không phải toàn bộ máy chủ
      Máy chủ thực tế thường có mức sử dụng CPU lên tới 70~80% (cao hơn nữa thì tail latency sẽ xấu đi rất nhanh)
      Nếu ở full load mà CPU chỉ dùng 5% thì đó là dấu hiệu thiếu tiến trình song song hoặc thiếu bộ nhớ
      Đây là chi tiết kỹ thuật nhỏ thôi, nhưng những sai sót như vậy có thể làm giảm độ tin cậy của bài viết này (nói với tư cách một fan của Bun)

    • Tôi có cảm giác kết luận đó giống như một kiểu hallucination do LLM tạo ra
      Đặc biệt phần kết luận rất giống văn phong lấy ra từ LLM
      "Điều khiến tôi hiểu ra là không phải các package manager được benchmark là sai, mà chúng là lời giải phù hợp với thời đại của chúng"
      "Điểm cần nhấn mạnh là cách tiếp cận của Bun không hẳn mang tính cách mạng, mà là kết quả của việc nhìn thẳng, tỉnh táo vào nguyên nhân khiến mọi thứ chậm đi ngày nay"
      "Việc cài package nhanh hơn 25 lần không phải phép màu, mà là hệ quả tự nhiên của việc xây dựng công cụ phù hợp với phần cứng hiện đại"

  • Dù chủ đề phức tạp, bài viết giải thích rất dễ hiểu và đơn giản nên tôi cực kỳ thích
    Thật đáng khâm phục khi vẫn còn những người đầy nhiệt huyết phá vỡ hiện trạng và dám nhận các bài toán khó
    Mỗi tháng phần cứng máy tính lại tiến bộ, trong khi phần mềm thì ngày càng chậm đi, điều đó thật sự có cảm giác bất thường
    Tôi mong ai cũng viết code hiệu quả hơn

    • Tôi không biết bun được viết bằng Zig
      Zig là một ngôn ngữ rất mới, nên thật thú vị khi thấy nó được dùng nghiêm túc trong thực tế
  • Tôi mới thử bun lần đầu và thấy rất ấn tượng
    Nhờ có server tích hợp sẵn và SQLite, chỉ cần cài mỗi bun là đủ nên việc phát triển thuận tiện hơn rất nhiều
    Bình thường tôi chỉ dùng vanilla js và vốn không thích hệ sinh thái node cho lắm, nên thấy mình lẽ ra nên dùng bun sớm hơn

    • Tôi đã thử Bun nhiều lần và trải nghiệm sử dụng rất hài lòng
      Nó cho cảm giác tốt hơn Node
      Nhưng lần nào rồi tôi cũng đụng phải một vấn đề chí mạng nên cuối cùng lại quay về Node
      Ban đầu là module crypto không tương thích với Nodejs (giờ đã được sửa), sau đó là Playwright không chạy trên Bun

    • Dạo này Node cũng hỗ trợ server tích hợp sẵn và SQLite
      Nếu cần nhiều tính năng hơn thì Hono cũng là một lựa chọn thay thế tốt

  • Tôi không thật sự hiểu đoạn bài viết giải thích rằng hardlink trên Linux và clonefile trên MacOS là tương đương nhau
    Với hardlink thì nếu sửa một bản sao, chẳng phải file trong mọi project đều sẽ bị thay đổi ngoài ý muốn sao?

  • Dù phần giải thích về mặt kỹ thuật khá phức tạp, bài viết vẫn được viết cực kỳ dễ đọc và vui nhộn, thật đáng nể

    • Lydia rất giỏi trong việc truyền đạt những khái niệm phức tạp theo cách dễ hiểu
      Tôi đã xem hầu hết các sản phẩm và video của cô ấy, và có thể cảm nhận được sự chuẩn bị rất kỹ lưỡng
      Nếu có thời gian, tôi rất khuyến khích mọi người xem các bài viết và nội dung YouTube của cô ấy
      Gần đây có lẽ cô ấy hoạt động ít hơn vì công việc hiện tại
  • Ở mục Binary Manifest Caching, có vẻ như thời gian benchmark của "npm (cached)" đã bị thiếu
    Chỉ có bun, bun (cached) và npm, và phần thống kê tóm tắt dường như cũng không khớp hẳn

  • Tôi rất thích văn phong của bài đăng này
    Có vẻ đây sẽ là một ví dụ rất tốt để tái sử dụng khi giải thích tầm quan trọng của io_uring
    Tôi cũng tò mò liệu bản cập nhật io gần đây trong Zig v0.15 có thể mang lại thêm lợi ích hiệu năng cho Bun hay không

  • Tôi đã chờ đợi bun hơn một năm rồi
    Tôi từng nghĩ 2025 sẽ là năm bun thật sự phổ biến, nhưng bất ngờ là đến giờ nó vẫn chưa nổi đến vậy
    Trong top 100 nghìn repo trên GitHub, tính đến năm 2025 thì ở các repo mới, npm được dùng nhiều hơn 35 lần và pnpm nhiều hơn 11 lần
    Deno cũng không nổi tiếng như tôi tưởng
    Tôi tò mò không biết lý do là gì
    Có phải vì runtime khó đạt tương thích hơn package manager?
    Tôi muốn nghe ý kiến từ những người đã thử bun nhưng không chọn dùng nó
    Thống kê tham khảo liên quan
    Bình luận HN liên quan

    • Tôi đã nhiều lần cố thích cả Bun lẫn Deno và cũng đã thử chúng vài lần, nhưng cuối cùng đều gặp lỗi chí mạng nên không thể tiếp tục dùng
      Vấn đề lớn nhất gần đây tôi gặp với Bun là stream bị đóng quá sớm
      Link issue liên quan
      Với Deno thì tôi gặp vấn đề rò rỉ bộ nhớ
      Link issue liên quan
      Cuối cùng tôi nghĩ hệ sinh thái Node sẽ tiếp nhận các ưu điểm của Bun/Deno trước

    • Bun là một tay chơi mới, được rót vốn venture capital, đang cạnh tranh với sản phẩm mã nguồn mở đã được kiểm chứng và đang thống trị là Node
      Có động cơ lock-in, và rốt cuộc thì nó cũng không khác Node về mặt nền tảng đến vậy
      Nó không có lợi thế chiến lược nào thật sự rõ ràng, cũng không mang lại điều gì mới mà Node không làm được
      Thực tế tôi chưa thấy trường hợp nào dùng nghiêm túc, chỉ thấy các trường hợp dùng nhẹ nhàng

    • Nhìn vào issue tracker thì có vẻ ngôn ngữ Zig không an toàn lắm nên crash xảy ra khá thường xuyên
      Tôi sẽ tiếp tục ở lại với Node

    • Tôi cũng tò mò ý kiến của người khác
      Theo tôi, Node là một dự án đã trưởng thành, mang tính dân chủ và đậm chất cộng đồng dẫn dắt
      Một phần cũng vì nó đã vượt qua rất tốt sự cố fork io.js
      Trong khi đó bun hay deno thì đều là các dự án được VC chống lưng, nên tôi không có cảm giác đó là cộng đồng dân chủ dẫn dắt

    • Tôi là fan cuồng của Bun
      Tôi dùng Bun cho mọi project có thể, và cả các script one-off cũng viết bằng Bun/TS
      Dù vậy, vẫn có một số issue tuy ít nhưng đáng lo nên tôi còn do dự chưa dám deploy production
      Ví dụ, khi chạy một webserver Express đơn giản trong Docker bằng bun thì nó từng bị treo
      Chỉ cần đổi sang node là chạy bình thường
      Một năm trước, tổ hợp Bun + Prisma cũng từng làm server chết vì rò rỉ bộ nhớ (chắc giờ đã được sửa rồi)
      Dù vậy tôi vẫn rất thích Bun, đến mức chấp nhận những nhược điểm đó vì nhìn chung nó giúp tiết kiệm thời gian phát triển
      Sự tiện lợi từ transpile, module, workspace v.v. là cực lớn
      Tôi hoàn toàn hiểu vì sao nó vẫn chưa phổ biến như npm

  • Đọc bài này thật sự rất thích thú
    Đây là một ví dụ cho thấy các nguyên lý khoa học máy tính quan trọng thế nào trong phát triển phần mềm ngoài đời thực
    Big O, tính cục bộ theo thời gian/không gian, độ phức tạp thuật toán, user/kernel space, file system, copy-on-write v.v.
    Trong kiểu phát triển package ở tầng thấp như thế này, gần như mọi khái niệm học trong chương trình CS đều được áp dụng vào thực tế

    • Thực ra cái này gần với software engineering (SE) hơn là computer science (CS)
      CS nghiên cứu tính toán và lý thuyết (ngôn ngữ lập trình, thuật toán, mật mã học, machine learning v.v.)
      Còn SE là việc áp dụng các nguyên tắc kỹ thuật để xây dựng phần mềm có khả năng mở rộng và độ tin cậy cao
  • Tôi không hiểu rõ vì sao việc đọc xong toàn bộ file nén rồi mới giải nén lại có lợi
    Tôi đoán rằng bắt đầu giải nén trước cả khi tải xong sẽ có lợi hơn, hơn cả bất lợi do số lần sao chép lại bộ nhớ tăng lên