Công bố Zstandard được triển khai bằng Rust
(trifectatech.org)- libzstd-rs-sys là dự án nén thứ ba của Quỹ Trifecta sau zlib và bzip2, đồng thời là bản phát hành zstd đầu tiên dựa trên Rust
- Zstd là định dạng nén được tối ưu cho CPU hiện đại, nhanh hơn gzip và cũng có tỷ lệ nén cao hơn, nên được kỳ vọng sẽ dần thay thế gzip trong lưu lượng web
- Crate zstd hiện có cho Rust biên dịch mã C từ source, nên cần toolchain C và hỗ trợ cho mục tiêu đích, khiến việc thiết lập trên Windows và WebAssembly có thể khó khăn
- Bản triển khai bằng Rust có thể được biên dịch thành thư viện C tương thích drop-in, và đang được kiểm chứng như một lựa chọn thay thế cho bản triển khai tham chiếu C bằng test suite, fuzz test và Miri
- Giải nén mặc định chậm hơn C vài phần trăm, nhưng mức giảm hiệu năng khoảng 3% là cái giá cho an toàn bộ nhớ, và có thể đạt hiệu năng ngang C bằng cờ thử nghiệm
Bản phát hành đầu tiên và ý nghĩa của bản triển khai Rust
- Trifecta Tech Foundation đã công bố bản phát hành đầu tiên của libzstd-rs-sys, dự án xử lý zstd, là dự án nén thứ ba sau zlib và bzip2
- Zstd là định dạng nén được thiết kế với CPU hiện đại trong đầu, có thể nhanh hơn đáng kể và đạt tỷ lệ nén tốt hơn gzip
- zstd đã được sử dụng rộng rãi và được kỳ vọng sẽ dần thay thế gzip trong lưu lượng web
- Trong Rust, zstd đã có thể được sử dụng qua crate zstd, nhưng crate hiện tại biên dịch mã C từ source nên cần toolchain C và hỗ trợ cho mục tiêu đích
- Việc thiết lập toolchain C cho Windows hoặc WebAssembly có thể khó, vì vậy một bản triển khai thuần Rust mang lại trải nghiệm dùng dependency tốt hơn cho nhà phát triển Rust
- Giống như các công việc với zlib và bzip2,
libzstd-rs-syscó thể được biên dịch thành thư viện C tương thích drop-in và hướng tới mục tiêu trở thành lựa chọn thay thế cho bản triển khai tham chiếu C - Bản triển khai tham chiếu C do Meta bảo trì và yêu cầu ký thỏa thuận đóng góp với Meta khi tham gia đóng góp, nên một bản triển khai độc lập, hiệu năng tốt và tương thích có thể củng cố hệ sinh thái mã nguồn mở
Kiểm chứng, hiệu năng và phần việc còn lại
- Bản triển khai tham chiếu ban đầu được chuyển đổi bằng
c2rust, sau đó việc dọn dẹp phần giải nén và dictionary builder đã hoàn tất - Mã Rust được biên dịch thành thư viện tĩnh C rồi được kiểm chứng bằng test suite của bản triển khai tham chiếu
- Fuzz test và Miri cũng được dùng để kiểm chứng tính đúng đắn của bản triển khai
- Bản pre-release được cung cấp tại libzstd-rs-sys v0.0.1-prerelease.2
-
Cái giá của an toàn bộ nhớ
- Hiệu năng giải nén mặc định chậm hơn bản triển khai tham chiếu C vài phần trăm
- Mỗi thay đổi được hợp nhất vào
mainđều được đo trên benchmark suite - Khi bật feature flag
unsafe-performance-experimental, hiệu năng sẽ ngang với hiệu năng C - Cờ này vô hiệu hóa kiểm tra biên ở 4 vị trí mà dữ liệu đầu vào được dùng để lập chỉ mục cấu trúc dữ liệu
- Với phần lớn người dùng, mức giảm hiệu năng khoảng 3% nhiều khả năng là cái giá chấp nhận được để đổi lấy an toàn bộ nhớ tốt hơn
- Nếu cần vắt đến phần hiệu năng cuối cùng, người dùng có thể chấp nhận rủi ro và bật cờ này; hành vi ở 4 vị trí đó sẽ khớp với C vốn không kiểm tra biên
-
Triển khai nén và tích hợp hệ sinh thái
- Phần nén vẫn đang tìm nguồn tài trợ
- Có chia sẻ mã giữa nén và giải nén nên một phần mã nén cũng đã được xem xét, nhưng phần lớn công việc dọn dẹp vẫn còn lại
- Benchmark để ngăn thoái lui hiệu năng nén đã được thiết lập, đồng thời đang dùng test suite của bản triển khai tham chiếu để kiểm tra việc tạo ra kết quả đúng
- Phần việc còn lại được tổng hợp tại Milestone 4: Encoder implementation
- Có một bản fork của
zstdsử dụnglibzstd-rs-systhay cho thư viện C, và nhóm phát triển mong muốn sau này được đưa ngược lên upstream - Với các API được dùng nhiều nhất, việc tích hợp tương đối đơn giản
- Ở feature
experimental, có sự không khớp khizstd-safedùng enum nhưng vì an toàn FFI lại phải dùngstruct
-
Tài trợ
- Công việc về giải nén được tài trợ bởi Chainguard, Astral, NLnet Foundation
- Sovereign Tech Agency đã đầu tư cho dictionary builder
1 bình luận
Ý kiến trên Lobste.rs
Đây thực sự là tin rất đáng mừng. Vài ngày trước tôi phải kéo cả
libc-devvào chỉ để build zstd vì một dependency, và đã tự hỏi liệu đã có ai nghiêm túc reimplement nó bằng Rust chưaHy vọng cộng đồng sẽ chấp nhận rộng rãi
Tôi đang làm một dự án dựa trên WireGuard bằng Rust, nên cũng đang dùng nhiều thư viện mật mã Rust. Tính an toàn bộ nhớ là một ưu điểm rõ ràng, nhưng không phải thư viện nào cũng đã được kiểm toán bảo mật như các thư viện C lâu đời
Rốt cuộc điều tôi băn khoăn là: việc viết lại các thuật toán này bằng Rust có thật sự đáng với chi phí bỏ ra không?
Những phần mã “nhàm chán” không phải mật mã như parsing, trạng thái giao thức, quản lý buffer phải hoạt động đúng thì hệ thống mới an toàn. Nếu kẻ tấn công có thể gửi một gói tin ma thuật để thực thi mã tùy ý, họ sẽ không bận tâm tới phân tích mật mã cao cấp hay side-channel timing để rút thời gian giải mã từ hàng nghìn năm xuống vài chục năm
Cả hai phía đều an toàn bộ nhớ, và bạn chỉ cần giữ ranh giới unsafe FFI thật hẹp. Các thư viện mật mã Go hiện trưởng thành hơn những gì Rust, hay chính xác hơn là hệ sinh thái crates.io, đang cung cấp
Tôi muốn biết liệu có ai biết tài liệu nào giải thích rõ khi nào nên dùng hậu tố
-sysvà-rs-syskhông. Theo trực giác tôi từng nghĩ-syslà dành cho crate bọc các thư viện hệ thống không được viết bằng RustNhưng trong khuôn đó thì hậu tố
-rs-syslại khó hiểu, nên có lẽ trực giác của tôi đã sai. Có ai biết nguồn có thẩm quyền nào không?*-sys: đây là một quy ước cũ và được dùng rộng rãi, có mô tả tại https://doc.rust-lang.org/cargo/reference/… . Nhưng nó hoàn toàn không phù hợp với crate nàylib*: ai cũng biết đó là thư viện rồi, trong Rust tiền tố này không phải quy ước, và ở link trên cũng gần như nói thẳng là nên tránh dùng cùng*-sys.libzstd-syscòn có thể khiến người ta nghĩ nó sẽ link tớiliblibzstd. Nhân tiện, ngay cả ngoài Rust tôi cũng từng thấy tên cóliblặp đôi thật*-rs: như https://rust-lang.github.io/api-guidelines/naming.html đã nói, “mọi crate đều là Rust! Không cần liên tục nhắc người dùng điều đó”-systhường phơi ra giao diện kiểu C rất thô, có nhiều mã unsafe bên trong, và thường build hoặc link tới thư viện bên ngoàiCòn tên
-rs-systhì tôi thấy được dùng kém nhất quán hơn. Có vẻ nó dùng cho các thư viện build mã ngoài đã được gói lại trong một crate Rust, chẳng hạn một bản triển khai Rust còn dang dở vẫn còn phần C, hoặc mã hỗ trợ Rust cho một sys cratelibzstdlà tên gốc. Thư viện C thường cólibtrong tên, và thay vì đổi cho hợp quy ước Rust/Cargo thì họ giữ nguyên để tiện tham chiếu-rslà để phân biệt với bản triển khai C của Facebook, tức là một bản viết lại bằng Rust. Đây là một hậu tố khá phổ biến trong nhiều dự án Rust, tương tự kiểu thư viện Python đặt tên nhưpysomething-syslà vì bản triển khai này là bản thay thế drop-in phơi ra C API unsafe. Từ góc nhìn người dùng Cargo, đây không phải thư viện Rust. Nó không có giao diện Rust và được gọi như mã C với các hàm CVì vậy đây không phải
-rs-sys, mà là phiên bản-syscủalibzstd-rsVì sao nên chọn cái này thay vì ruzstd? Có phải đầu tư vào crate hiện có sẽ tốt hơn không?
Port 1:1 cho phép đạt tốc độ tương tự và tương đương tính năng bằng một quá trình chuyển đổi mã khá thẳng, thay vì phải tự tìm lại cách tạo ra một compressor nhanh và đầy đủ tương đương trên một codebase khác
“Bản triển khai tham chiếu bằng C do Meta duy trì, và nếu muốn đóng góp thì phải ký thỏa thuận cộng tác viên với Meta”
Một điều thú vị tôi mới biết gần đây là bản triển khai zstd tham chiếu do Facebook quản lý cũng đang được viết code bằng LLM và còn là dependency của openssl, nên tôi hoàn toàn ủng hộ việc có thêm nhiều lựa chọn thay thế
“Ở cấu hình mặc định, hiệu năng giải nén của bản triển khai chúng tôi chậm hơn bản tham chiếu C vài phần trăm”
Chỉ cần biết câu này là đủ để hiểu về dự án
Để tham khảo, ngay sau câu bạn trích thì bài còn viết tiếp như sau
“Tuy nhiên, nếu bật cờ tính năng
unsafe-performance-experimentalthì hiệu năng sẽ ngang với C, nên chúng tôi cho rằng mức suy giảm này là hợp lý. Cờ này tắt 4 lần kiểm tra biên tại bốn vị trí nơi dữ liệu đầu vào được dùng để lập chỉ mục cấu trúc dữ liệu. Với phần lớn người dùng, mức giảm hiệu năng khoảng 3% có lẽ là cái giá chấp nhận được để đổi lấy an toàn bộ nhớ tốt hơn. Nếu thực sự cần vắt kiệt hiệu năng cuối cùng, bạn có thể tự chịu trách nhiệm bật cờ này. Hành vi ở bốn vị trí đó sẽ giống với C không kiểm tra biên, và có vẻ đang chạy ổn trong nhiều hệ thống production”