3 điểm bởi GN⁺ 2025-06-19 | 1 bình luận | Chia sẻ qua WhatsApp
  • Crate bzip2 đã thay thế phụ thuộc mã C bằng triển khai Rust 100%
  • Hiệu năng nhìn chung được cải thiện so với trước đây, đồng thời việc cross-compile cũng trở nên dễ dàng hơn
  • Triển khai Rust cải thiện cả tốc độ nén lẫn giải nén dữ liệu so với phiên bản C
  • Các vấn đề phụ thuộc thư viện như xung đột symbol được giảm đi đáng kể
  • Sau khi trải qua kiểm toán bảo mật, các lỗi logic nghiêm trọng đã được sửa và độ ổn định đã được xác minh

Phát hành bzip2 crate 0.6.0 và chuyển sang nền tảng Rust

  • Hôm nay bzip2 phiên bản 0.6.0 đã được phát hành
  • Từ nay, mặc định nó sử dụng libbz2-rs-sys, một triển khai thuật toán bzip2 dựa trên Rust do nhóm tự phát triển
  • Với sự chuyển đổi này, bzip2 crate đã nhanh hơn và việc cross-compile cũng dễ hơn
  • Crate libbz2-rs-sys cũng có thể được build dưới dạng thư viện động C. Nhờ đó, các dự án C cũng có thể tận dụng các cải thiện về hiệu năng

Vì sao có sự chuyển đổi này?

  • Thuật toán bzip2 được tạo ra từ thập niên 90, hiện nay không còn được dùng rộng rãi, nhưng vẫn cần thiết trong nhiều giao thức và thư viện để tuân thủ đặc tả
  • Nhiều dự án không phụ thuộc trực tiếp, nhưng lại phụ thuộc vào bzip2 ở đâu đó sâu trong cây phụ thuộc
  • Dựa trên kinh nghiệm tích lũy từ zlib-rs, lần này chúng tôi đã hiện đại hóa triển khai bzip2
  • Các chi tiết triển khai của crate libbz2-rs-sys đã được đề cập trong bài blog trước. Ở đây sẽ tập trung vào các lợi ích của lần chuyển đổi này

Hiệu năng được cải thiện

  • Triển khai Rust nhìn chung cho hiệu năng cao hơn phiên bản C
  • Trong một số trường hợp hiệu năng tương đương, nhưng không có trường hợp nào chậm hơn
  • Hiệu năng nén: trong bzip2 có tùy chọn level, nhưng ảnh hưởng đến hiệu năng là không đáng kể
  • Kết quả thử nghiệm cho thấy trên các tệp mẫu tiêu biểu, phiên bản Rust nhanh hơn hơn 10%

Nén:

Tệp C (chu kỳ thực thi) Rust (chu kỳ thực thi) Thay đổi tương đối
sample3.ref (level 1) 38.51M 33.53M -14.87%
silesia-small.tar (level 1) 3.43G 3.00G -14.30%
silesia-small.tar (level 9) 3.47G 3.17G -9.66%

Ở tác vụ giải nén cũng cho thấy hiệu năng được cải thiện trong mọi trường hợp:

Tệp C (chu kỳ thực thi) Rust (chu kỳ thực thi) Thay đổi tương đối
sample3.bz2 2.53M 2.42M -4.48%
sample1.bz2 9.63M 8.86M -8.63%
sample2.bz2 20.47M 19.02M -7.67%
dancing-color.ps.bz2 87.46M 83.16M -5.17%
re2-exhaustive.txt.bz2 1.89G 1.76G -7.65%
zip64support.tar.bz2 2.32G 2.11G -10.00%

Tuy nhiên, trên môi trường macOS đôi khi có biến động ở số liệu giải nén. Do giới hạn của công cụ đo hiệu năng nên khó phân tích nguyên nhân

Hỗ trợ cross-compile

  • Việc cross-compile các dự án Rust có phụ thuộc C thường hoạt động ổn nhờ crate cc, nhưng khi thất bại thì việc debug cực kỳ khó khăn
  • Trong quá trình link thư viện hệ thống rất dễ phát sinh các vấn đề ngoài dự kiến, và ở một số môi trường như build WebAssembly thì đây trở thành trở ngại thực sự
  • Việc chuyển sang triển khai Rust khiến các vấn đề liên quan đến C biến mất hoàn toàn
  • Giờ đây có thể cross-compile sang Windows, Android, WebAssembly và các nền tảng khác mà không có điểm gì đặc biệt cần lưu ý
  • Đây là ưu điểm lớn không chỉ về trải nghiệm người dùng mà còn ở góc độ bảo trì

Mặc định không còn xung đột symbol (export)

  • Với phụ thuộc C, cần export symbol trong các khối extern của Rust, nên nếu phụ thuộc khác cũng export cùng symbol thì sẽ xảy ra xung đột
  • libbz2-rs-sys được thiết kế để mặc định không export symbol
  • Vì vậy sẽ không xảy ra xung đột symbol với các thư viện bên ngoài khác. Nếu cần thì cũng có thể bật export bằng feature flag

Chạy kiểm thử dựa trên MIRI

  • Để triển khai bzip2 hiệu năng cao trong Rust, việc dùng unsafe code là không thể tránh khỏi, và việc tái tạo giao diện C cũng cần nhiều unsafe code
  • May mắn là có thể chạy và kiểm thử đoạn mã này trong môi trường MIRI
  • Hơn nữa, các thư viện hoặc ứng dụng cấp cao hơn sử dụng bzip2 giờ đây cũng có thể chạy kiểm thử bằng MIRI

Kết luận

Giờ đây bzip2 crate đã nhanh hơn. Nó mang lại trải nghiệm tốt hơn một cách tự nhiên đến mức gần như bạn không còn phải bận tâm về nó nữa

1 bình luận

 
GN⁺ 2025-06-19
Ý kiến trên Hacker News
  • Xét khả năng bản triển khai của Trifecta Tech thay thế bản triển khai chính thức đang được các bản phân phối Linux sử dụng, điều này được cho là không phải bất khả thi, vì trước đây Fedora từng thay thế Adler zlib cũ bằng zlib-ng. Ý chính là chỉ cần cung cấp C ABI tương thích với bản gốc
    • Nếu từ năm 2019 đến nay không còn bản phát hành upstream nào, thì có người đặt câu hỏi liệu bản triển khai này thực chất đã đơn giản là hoàn thiện rồi hay chưa. Nếu không còn lỗi nào cần sửa hay tính năng nào cần thêm, thì như vậy tự nó cũng đã đủ tốt
    • Việc Ubuntu dùng sudo được viết bằng Rust khiến ý tưởng thay thế kiểu này được xem là hoàn toàn có khả năng xảy ra
    • Có ý kiến rằng Trifecta Tech đang cung cấp C ABI tương thích khá tốt, nhưng rốt cuộc vẫn cần ai đó thực sự thực hiện công việc này thì thay đổi mới diễn ra
    • Cũng nhắc đến việc mục tiêu của uutils là hướng tới những thay thế chính thức như vậy, đồng thời chia sẻ liên kết đến trang chủ uutils
    • Sau khi xem nhanh thì có vẻ tích cực vì đã có cấu hình cargo-c, nhưng do namespace khác nhau nên các chương trình C sẽ không tự động nhận diện nó là libbz2 hiện có. Người bình luận nói mình không đủ quen với các symbol của bzip2 để biết ABI có tương thích hoàn toàn hay không. Việc tự duy trì bản triển khai GNU operating system tốn quá nhiều thời gian nên khó làm, nhưng nếu có thời gian thì sẵn sàng nhận PR cho dự án thử nghiệm platypos
  • Tôi đang dùng crate này để xử lý hàng trăm TB dữ liệu Common Crawl. Tốc độ nhanh hơn nên rất hài lòng
    • Có người hỏi tại sao lại dùng bz2 ở đây. Với trường hợp chỉ cần thực hiện một lần chuyển đổi khối lượng lớn thì nghe nói chuyển sang zstd có lợi rất nhiều, và khi mức nén càng cao thì gần như ở mọi mặt nó đều tốt hơn bzip2
    • Có người hỏi liệu dữ liệu Common Crawl có được công bố dưới dạng torrent hay không
    • Chia sẻ cảm nhận rằng mức cải thiện 14% về tốc độ nén là khá ấn tượng
  • Có người thắc mắc liệu bản triển khai này về cơ bản có khắc phục được 11 CVE còn tồn đọng hay không. Trớ trêu là crate bzip2 cũng từng bị báo cáo CVE, kèm liên kết liên quan
    • Có ý kiến cho rằng sự đối chiếu giữa các lỗ hổng kiểu “runtime failure trên file lớn” được báo trong crate này và vấn đề “bounds miss” trong bản viết bằng C là khá thú vị. Họ cũng tò mò liệu các lỗ hổng bounds miss như vậy có thực sự có thể dẫn tới thực thi mã hay không
    • Trích dẫn thông báo rằng “crate bzip2 có lỗ hổng ở các phiên bản trước 0.4.4”. Thông tin bổ sung là hôm nay phát hành 0.6.0
  • Trước câu hỏi “tại sao lại cố cải tiến một thuật toán từ thập niên 90”, có người nói họ tò mò hiện nay người ta dùng những thuật toán nào. Họ nhắc đến zstd và chia sẻ liên kết benchmark so sánh thuật toán nén
  • Có người thắc mắc nếu backend codegen của trình biên dịch cho C và Rust là giống nhau thì tại sao lại có thể tăng tốc. Họ nêu ra nhiều khả năng như auto-simd của Rust, tối ưu hóa thủ công, hoặc tận dụng các thư viện tối ưu hóa mới
    • Một phỏng đoán là Rust có thể cung cấp nhiều gợi ý hơn cho bộ sinh mã. Ví dụ, khác với con trỏ C, người viết ít phải lo hơn về vấn đề aliasing. Có kèm liên kết giải thích Aliasing
    • Có ý kiến cho rằng C thật sự không phù hợp để viết mã hiệu năng cao hiện đại. Từ C99 đến C21 trong gần 20 năm, bản thân ngôn ngữ này thiếu các cơ chế để tận dụng các lệnh mới như clz, popcnt, clmul, pdep... theo cách gọn gàng. Chỉ riêng việc hỗ trợ các chỉ thị trừu tượng như vậy cũng đã giúp ích rất nhiều cho kiểu tối ưu hóa mã này
    • Có người cho rằng viết lại bằng bất kỳ ngôn ngữ nào cũng mở ra cơ hội cải thiện tốc độ, chứ không phải Rust mặc định đảm bảo điều đó
  • Có người bày tỏ hy vọng tôi hoặc Prossimo sẽ viết lại theo cách tương tự các giao thức Internet cốt lõi (BGP, OSPF, RIP...) cùng các bản triển khai định tuyến, DNS server, v.v.
    • Họ giới thiệu các quỹ trong vài năm gần đây đã hỗ trợ việc viết lại các công cụ cốt lõi của Internet và OS bằng Rust cùng các ngôn ngữ an toàn khác, gồm dự án của NLnetSovereign Tech Fund. Ví dụ đi kèm là dự án BGP in Rust
    • Memory Safety Initiative cũng giới thiệu các nỗ lực viết lại an toàn cho những dịch vụ cốt lõi như TLS và DNS, nên phần nào trùng với bối cảnh đề xuất này
    • Có một nhà phát triển đã tạo ra Ironsides DNS bằng SPARK Ada, ngôn ngữ này hỗ trợ các chứng minh hình thức mạnh hơn
  • Có ý kiến cho rằng trên macOS, dù không có profiler perf thì vẫn có thể phân tích hiệu năng khá tốt bằng dtrace. Script flame graph gốc viết bằng Perl cũng dùng dtrace, và bản flame graph được viết lại bằng Rust cũng sử dụng cách này. Dù thiếu một số metric như cache miss hay micro instruction retired, nó vẫn rất hữu ích
  • Một bình luận đùa rằng cần viết lại Rust bằng Javascript
  • Có người hỏi liệu nó có hỗ trợ giải nén song song như lbzip2 hay không, hoặc có thể xử lý song song thông qua việc quét trước block magic chẳng hạn. Sau khi chỉnh sửa, họ kết luận là “có lẽ không hỗ trợ”
  • Có người kể lại trải nghiệm Lbzip2 cho tốc độ giải nén rất nhanh nhờ tận dụng toàn bộ các lõi CPU. Dù đã là năm 2025, nhiều chương trình lớn như Python vẫn chỉ dùng 1 lõi, điều này khiến họ thấy đáng tiếc
    • Có người chỉ ra rằng họ không thật sự hiểu tình hình của Python