Rustで実装したZstandardを発表
(trifectatech.org)- libzstd-rs-sysは、Trifecta Foundationの zlib・bzip2 に続く3つ目の圧縮プロジェクトで、zstdとして初のRustベースのリリース
- Zstdは現代的なCPUに合わせた圧縮形式で、gzipより高速かつ圧縮率も高く、Webトラフィックではgzipを段階的に置き換えていくと見込まれる
- 既存のRust製 zstd クレートはCコードをソースからコンパイルするため、Cツールチェーンとターゲット対応が必要で、Windows・WebAssembly 向けの設定が難しい場合がある
- Rust実装はドロップイン互換のCライブラリとしてコンパイル可能で、テストスイート・ファズテスト・Miri により C 参照実装の代替として検証が進められている
- デフォルトの展開はCより数パーセント遅いが、約3%の性能低下はメモリ安全性のコストであり、実験的フラグでC性能に合わせることもできる
初回リリースとRust実装の意味
- Trifecta Tech Foundation は、zlib、bzip2に続く3つ目の圧縮プロジェクトとして、zstdを扱う libzstd-rs-sys の初回リリースを発表
- Zstdは現代的なCPUを念頭に設計された圧縮形式で、gzipよりはるかに高速で、より高い圧縮率を実現できる
- zstdはすでに広く使われており、Webトラフィックではgzipを段階的に置き換えていくと予想される
- Rustではすでに zstd クレートで zstd を使えるが、既存クレートはCコードをソースからコンパイルするため、ターゲット向けのCツールチェーンとターゲット対応が必要になる
- Windows や WebAssembly 向けの C ツールチェーン設定は難しいことがあり、純粋なRust実装はRust開発者にとって依存関係の扱いをより良い体験にする
libzstd-rs-sysは zlib・bzip2 の取り組みと同様に、ドロップイン互換のCライブラリとしてコンパイルでき、C参照実装 の代替を目指している- C参照実装は Meta が保守しており、貢献時には Meta とコントリビューター契約を結ぶ必要があるため、独立していて高性能かつ互換性のある実装はオープンソース生態系の強化につながる
検証、性能、残る作業
- 初期の参照実装は
c2rustで変換され、その後に展開処理と辞書ビルダーの整理作業が完了した - RustコードはC静的ライブラリとしてコンパイルされたうえで、参照実装のテストスイートにより検証されている
- ファズテストと Miri も実装の正確性を検証するために使われている
- プレリリースは libzstd-rs-sys v0.0.1-prerelease.2 で提供されている
-
メモリ安全性のコスト
- デフォルトの展開性能はC参照実装より数パーセント遅い
mainにマージされる各変更は ベンチマークスイート で測定されるunsafe-performance-experimental機能フラグを有効にすると、C性能と一致する- このフラグは、入力データがデータ構造のインデックスに使われる4か所の境界チェックを無効化する
- 大半のユーザーにとって、約3%の性能低下は、向上したメモリ安全性のために受け入れ可能なコストである可能性が高い
- 最後の性能まで必要なら、リスクを受け入れてこのフラグを有効にでき、その4か所の動作は境界チェックを行わないCと一致する
-
圧縮実装とエコシステム統合
- 圧縮部分はまだ資金調達先を探している
- 圧縮と展開の間でコード共有があるため、圧縮コードも一部は確認されているが、大半の整理作業はまだ残っている
- 圧縮性能の退行を防ぐためのベンチマークが設定されており、参照実装のテストスイートで正しい結果が生成されるか確認中
- 残る作業は Milestone 4: Encoder implementation にまとめられている
- Cライブラリの代わりに
libzstd-rs-sysを使うzstdフォークがあり、将来的にはアップストリームへの反映を望んでいる - 最もよく使われるAPIでは統合は比較的容易
experimental機能ではzstd-safeが enum を使う一方、FFI安全性のためにstructを使う必要があるという不一致がある
-
支援
- 展開作業は Chainguard、Astral、NLnet Foundation が資金提供した
- 辞書ビルダーには Sovereign Tech Agency が投資している
1件のコメント
Lobste.rsの意見
本当にうれしいニュース。数日前、依存関係の一つのせいで zstd のビルドをするために libc-dev を引っ張ってくる必要があり、誰かが Rust で本気で再実装したことがあるのか気になっていた
コミュニティで広く採用されるといい
WireGuard ベースのプロジェクトを Rustで作っているので、いろいろな Rust の暗号ライブラリを取り込んでいる。メモリ安全性という明確な利点はあるが、古い C ライブラリと違って、どれも セキュリティ監査を受けているわけではない
結局気になるのは、こうしたアルゴリズムを Rust で書き直すことにそれだけのコストを払う価値があるのかという点
パース、プロトコル状態、バッファ管理のような「退屈な」非暗号コードが正しく動いてこそ、システムは安全になる。攻撃者は、任意コード実行が可能になる魔法のようなパケットを送れるなら、何千年もかかる解読を数十年に縮める高度な暗号解析やタイミングサイドチャネルに頼ったりはしない
どちらもメモリ安全で、狭い unsafe な FFI 境界だけを置けばよいという利点がある。Go の暗号ライブラリは、現時点では Rust、より正確には crates.io エコシステムで提供されているものより成熟している
-sysと-rs-sysの接尾辞をいつ使うべきか、文書化された説明を知っている人はいないだろうか。直感的には、-sysは Rust で書かれていないシステムライブラリをラップする crate 用だと思っていただがその枠組みだと
-rs-sys接尾辞がしっくりこないので、自分の直感が間違っていたようだ。権威ある出典を知っている人はいるだろうか?*-sys: 古くからあり広く使われている慣例で、https://doc.rust-lang.org/cargo/reference/… で説明されている。だがこの crate にはまったく当てはまらないlib*: ライブラリであることはすでに分かっているし、Rust ではこの接頭辞は慣例的ではなく、上のリンクでも*-sysとともに半ば明示的に避けるよう示されている。libzstd-sysだとliblibzstdにリンクするものと期待されかねない。付け加えると、Rust とは無関係に実際に二重lib名を見たこともある*-rs: https://rust-lang.github.io/api-guidelines/naming.html にある通り、「すべての crate は Rust だ! ユーザーにそれを何度も思い出させる必要はない」-syscrate はたいてい非常に生の C 風インターフェースを公開し、内部に unsafe コードが多く、たいていは外部ライブラリをビルドまたはリンクする-rs-sysという名前は、もっと一貫性なく使われているのを見てきた。Rust crate の中でラップし直した外部コードをビルドするライブラリ、たとえばまだ C 部分が残っている未完成の Rust 実装や、sys crate 向けの Rust サポートコードに使われるようだlibzstdは元の名前だ。C ライブラリは名前にlibを含む傾向があり、Rust/Cargo の慣例に合わせて変える代わりに、参照のためそのまま残したのだろう-rsは Facebook の C 実装と区別するための Rust 再実装版という印だ。多くの Rust プロジェクトでよく使われる一般的な接尾辞で、Python ライブラリがpysomethingのように命名するのに近い-sysは、この実装が unsafe な C API を公開するドロップイン置き換えだからだ。Cargo ユーザーの視点では Rust ライブラリではない。Rust インターフェースはなく、C 関数を持つ C コードのように呼び出すつまり
-rs-sysなのではなく、libzstd-rsの-sysバージョンということなぜ ruzstd ではなくこちらを選ぶべきなのか? 既存の crate に投資したほうが良いのでは?
1:1 ポーティングなら、別のコードベースの上で同じく高速で完全な圧縮器をどう作るかを一から解き直すのではなく、比較的まっすぐなコード変換で似た速度と機能同等性を確保できる
「C の参照実装は Meta が管理しており、貢献するには Meta と貢献者契約に署名する必要がある」
最近知って少し面白かった事実だが、Facebook が管理する参照 zstd 実装も LLM でコーディングされていて、しかも openssl の依存関係でもあるので、代替が増えることには全面的に賛成だ
「デフォルト設定では、我々の実装の展開性能は C の参照実装より数パーセント遅い」
このプロジェクトについて知るべきことはこれですべてだ
参考までに、引用した文のすぐ後にはこう続いている
「ただし
unsafe-performance-experimental機能フラグを有効にすると C の性能と同等になるため、この性能低下は正当化できると考えています。このフラグは、入力データがデータ構造のインデックスに使われる4か所で境界チェック4つを無効化します。大半のユーザーにとって約3%の性能低下は、メモリ安全性向上のために受け入れ可能なコストである可能性が高いです。本当に最後の性能まで必要なら、自己責任でこのフラグを有効にできます。この4か所での動作は境界チェックを行わない C と同じであり、多くの本番システムで問題なく動作しているようです」