ディスカッション (32件)
Rustは「圧倒的なパフォーマンス」と「ゼロコスト抽象化」を掲げていますが、実際の現場ではどうなのでしょうか?先日開催されたC++Russia 2026にて、Zack Akimovと共にその実態を徹底調査し、登壇発表を行いました。私たちはRustのパフォーマンスにおけるトレードオフと、現在のコンパイラがそれらをどの程度最適化できているのかについて、体系的なレビューを行いました。既存資料の精査、コンパイラの解析・修正、そして膨大なパフォーマンスデータの収集を経て、現時点で最も包括的な分析結果に仕上がったと自負しています。150枚を超えるスライドには講演の核心部分をまとめており、調査過程で得られた追加データや詳細な資料はGitHubリポジトリ( https://github.com/yugr/rust-slides/ )で公開しています。今後のRustパフォーマンスに関する議論の土台になれば幸いです。フィードバックやご意見は大歓迎ですので、ぜひお寄せください。
やあ、みんな。スレチな質問で申し訳ないんだけど、このトークの録画って公開されてる?
まだだよ。それにどっちにしろ英語じゃないし :(
ロシア人だから全然問題ないよ!
運営にできるだけ早く公開するようお願いしておいたよ。公開されたらここにYouTubeリンクを貼るね。とりあえずリポジトリにロシア語のスライドも入ってるよ。
すごくいい調査だね、シェアしてくれてありがとう!C/C++の世界から来た身としては、パフォーマンスに影響する微妙な違いを知れるのは最高に興味深いよ。
ありがとう!実はそれがまさに私のモチベーションだったんだ。Rustを学び始めたとき、小さくてもインパクトのある違いに気づかずにはいられなくて、それを集め始めたんだよね。そしたら、これって他の人にとっても興味深い内容になるんじゃないかと思ったんだ。
素晴らしい内容!Rustの追加チェックによる実際のコストがわかってよかった。数パーセントっていうのは大きい気もするけど、同時にそれだけの価値はあるってことだね。
そうなんだ。でも一つ注意点があって、それはプロファイルされてホットスポットが最適化された成熟した産業用プロジェクトにおける2%っていう数字なんだ。それにこれは平均的な速度低下であって、最後のスライドでもわかるようにp95だと10%くらいになるよ。私にとっての最大の成果は、Hardened C++とRustがパフォーマンスの面で非常に似ていることを(安全性は劣るにしても)理論と実践の両面で示せたことかな。
ハードニングされたC++は、理論上も実践上もパフォーマンスと安全性の面でRustと非常に似ている。
「ハードニング」や「安全性」をどう定義しているか分からないけど、互換性を維持したままのC++のハードニングで、Rustと同等の安全性を確保することなんて不可能だよ。少なくとも実務や商用開発の現場ではね。
「(互換性を保つ限り)C++のハードニングをどれだけ重ねても、安全性という点でRustと同等にはならない」という意見には概ね同意だけど、細かなニュアンスが重要だね。境界チェックに関しては(メモリ安全性の一般論は別として)、ハードニングされたC++もRustと同等のチェックは行うけれど、コンテナサイズに関する情報が欠けているケースがほとんど(-Wunsafe-buffer-usageはコードの書き換えという代償を払って、この問題を解決しようとしている)。元のコメントを更新したよ。
まだスライドをじっくり読んでないからブックマークしたよ。「ゼロコスト抽象化」って響きはいいけど、実際にいじり始めると「どの抽象化が?」「どうコンパイルされて?」「どのターゲットに対して?」って話になるからね。掲示板でなんとなく噂話するんじゃなくて、実際に体系的な調査をしてくれたことに感謝するよ。今週、リカバリーライドで足が死んでて脳が暇な時に読むつもり。
その通り、条件がたくさんあるんだよね。スライドでは簡潔にまとめる必要があったから、詳細はリポジトリのMarkdownファイルを見てみて。
くそっ、俺もちょうどゼロコスト抽象化について同じようなコメントをしたところだよ。おっしゃる通り、100%その通りだと思う。
うわ、めちゃくちゃ深い研究だね!タイトルが地味すぎて、内容の凄さが伝わりきってないのがもったいない。
実は、このタイトルでも煽りすぎかなと心配してたんだよ :) 私たちの目的は純粋な調査であって、RustとC++の不毛な争いを再燃させることじゃないからね。
スライド44はさらなる最適化の余地がありそうだよ:
foo:
cmp rdx, rsi
jae .LBB0_2
mov eax, dword ptr [rdi + 4*rdx]
ret
.LBB0_2:
push rax
lea rax, [rip + .Lanon.1]
...
call qword ptr [rip + panic_bounds_check]
C++で同じことをすると.foo.coldラベルが付くから、関数の「失敗パス」セクションがライブラリのコールドセクションに移動されて、i-cacheを圧迫しないはずなんだよね。
たぶんGCCとLLVMの違いだろうけど、気にはなる :/
スライド79(シンボルのローカライゼーション):うわ、これほどパフォーマンスに影響するとは意識したことがなかったよ。
スライド120(包含範囲の問題):これって新しい方式の包含範囲 で解決済みかな?次のエディションで入るといいんだけど。
詳細なコメントありがとうございます。
スライド44はさらなる最適化の余地がありそうだよ
本当だ、その通りですね!Godboltが(親切心からか)ディレクティブを隠していたせいで気づきませんでした。
Rustパイプラインにおけるコールドセクション不足に関連する様々な問題は、こちら で分析しています。現状、HoldColdSplittingもMachineFunctionSplitterもデフォルトでは有効になっていません(MFSについてはこちら の通り、ブロックされています)。
スライド120(包含範囲の問題):これは新しい方式の包含範囲で解決済みかな?
これは残念ながら見落としていた点です。作業を開始したのが約1年前で、1.87ベースで進めていたもので。
Rustパイプラインにおけるコールドセクション不足に関連する様々な問題は、...で分析しています。
リンクありがとう。
これは残念ながら見落としていた点です。作業を開始したのが約1年前で、1.87ベースで進めていたもので。
新しいレンジの実装は確かにごく最近のものだからね。
主な動機は、(1)それらをCopyにすること、(2)RangeInclusiveのイテレーション性能の向上、の2点だよ。
前述の通り、チェーンのようなイテレータは内部イテレーション(.for_eachなど)ではうまく動くけど、LLVMがチェーンの各ステージ間でループを分割してくれないせいで、外部イテレーションだとパフォーマンスが出ない。古いRangeInclusiveは結局チェーンのようなイテレータだったから、どうチューニングしても最適化が効かないケースが必ずあったんだ。
新しいRangeInclusiveは(Iteratorではなくなったので)シンプルでコピー可能になり、IntoIteratorを実装して_別の_イテレータ型を生成するようになった。この新しいイテレータなら、ループの_前_に様々な条件で特化させることができる。例えば、endを安全にインクリメントできると判断できれば、startからend+1までの「排他的」なループに変換できるといった具合さ。
end+1が一度安全に計算されれば、startからend+1までのループはオーバーフローしないはず…なんだけど、まあ最適化器が予期せぬ失敗をすることもあるからね :)
Rustは重要な場面でC++よりわずかに遅いし、tokioやasyncは悪夢というか信じられないほど遅い。「ゼロコスト抽象化」なんてのは、ベンチマークで突っ込んで掘り下げてみると、ある側面では看板倒れだよ。ただ、公正に評価するなら、C++と(現実的な環境で)ベンチマーク比較すれば、40個中33個くらいはRustが負けるんじゃないかな…。stdioの処理は少なくとも良いけどね。でも本当に狂ってるのは、コンテンションの壁(ソフトウェアにおいて極めて重要)さえ解決できていないことだよ。まあ、すべてを「unsafe」に書き換えればボトルネックを回避できるかもしれないけど、それだと結局、余計な手間をかけたC言語を書いてるだけで、結局言語の檻と戦う羽目になる。
信じられないのは、これほど多くのボトルネックを抱えているのに、Rustがまるで言語の最終形態だと決めつけている人が多いことだ。私にとって一番引っかかるのは、C++から30年も経って作られたものが、こんなにも持ち上げられているという現実だよ。70年代にBやCを生み出していた人たちと比べて、今のテクノロジーを使ってこれかと思うと、正直呆れる。
まあ、@kain が言及している新しい何かが登場すれば、すぐに追い抜かれるだろうけどね。
低評価は下にどうぞ👇
「Rustはこんなに速い」と言われる変換事例のほとんどは、Python(や他のインタープリタ言語)からの移行だったり、アルゴリズムを改善したり、あるいは古いツールでは不可能だったレガシーな互換性を切り捨てただけ、というケースがほとんどだよね。
この界隈の狂信的なRust文化については、もっとみんな文句を言ってもいいと思う。Rustは単なる言語であって、先行言語と比べて優れている部分もあれば劣っている部分もある。言語としての穴はまだあるし、複雑さは増す一方だ。「C++は肥大化しているからRustを使おう」なんて論調も、Rustが成熟して機能や複雑さを取り込むにつれて消えつつあるよ。
ここで狂信者なんて一人も見かけてないけど。見かけるのは聞き飽きた古い誤解を繰り返してる連中ばかりで、明らかに言語に対する深い理解が欠けてるよね。C++に少しでも触れたことある人なら誰でも分かる通り、Rustの方が圧倒的にシンプルな言語だよ。もちろん、Rust自体が単純っていう意味じゃないけどね。
狂信者を発見
狂信者を発見
ずっとC++をメインにやってきて、2016年頃の比較的早い段階でRustを使い始めたんだ。Rustにはかなり感動したし、そこで得たプログラミングのアイデアをC++に持ち帰ったりもしたよ。ただ、言語としてのRustの成熟の仕方には正直ガッカリしてる。中途半端だったり、急いで実装されたように感じる部分が多すぎるんだよね。ボローチェッカーの仕組みもかなり強引というか、押し付けがましい感じがする。コンセプト自体は良いんだけど、深く触れば触るほど、言語設計の初期から組み込まれていたものというより、後付けで無理やりねじ込んだような感覚が拭えないんだ。
初心者で争うつもりはないんだけど、少し誤解があるみたいだよ。unsafeは、言語の「管理された庭(walled garden)」が予定通りにいかなかったからといって、しぶしぶ後付けされた逃げ道じゃない。むしろ、その「管理された庭」を広げるための仕組みだよ。unsafeを「余計な手間をかけたC言語」として使うのは、完全に無知な場合だけさ。
もしみんながなぜRustを高く評価しているのかを知る気がないなら、時間を割いて攻撃するようなことはやめた方がいいんじゃない?
いや、ただ今の未来にがっかりしてるだけ。毎日Rust使ってるけど正直嫌い。常にコンパイラと戦ってる感じ。まあ、これで3Dエンジンとかプログラミング言語を書いたりもしたけどさ(笑)
GPT 5.5によるスライドの要約だよ:
https://github.com/yugr/rust-slides/ は、Rustの「現実世界でのパフォーマンス特性」を、特にC/C++と比較して徹底的に掘り下げたレポジトリだ。
ライブラリやアプリというよりは、研究やトークの素材集に近く、以下が含まれている:
- 150枚以上のスライド
- ベンチマークデータ
- コンパイラの実験
- LLVMの調査
- ランタイムチェックの分析
- コンパイラパッチの概念実証
- 研究、Issue、事例へのリンク
核心的なテーマ
Rustの「ゼロコスト抽象化」は「概ね正しい」が、魔法のようにタダというわけではない。
Rustは多くの場合、C/C++に近いパフォーマンスを叩き出すけれど、特定の状況では測定可能なオーバーヘッドが発生する:
- 安全性チェック
- パニック処理の仕組み
- 初期化ルール
- イテレータの抽象化
- 境界チェック
- エイリアシングルール
- シンボルの可視性
- LLVMパイプラインの挙動
このレポジトリでは、そうしたオーバーヘッドがどこに存在し、最適化後にどこで消失するのかを定量化しようとしている。
大きな収穫
1. Rustは全体的に非常に高速
このレポジトリは「反Rust」ではない。
大まかな結論は:
Rustは通常、最適化されたC++と非常に近い性能を発揮する。
特に以下の条件で顕著だ:
- 成熟した最適化済みのコードベース
- CPU負荷の高いタスク
- LLVMがインライン展開やチェックの排除を行えるコード
2. 安全性はタダではないが、思ったより安い
レポジトリでは以下を詳細に検討している:
- 境界チェック、オーバーフローチェック、パニックのパス、強制初期化、ランタイムアサーション
結論としては:
- 多くのチェックは最適化で消える
- どうしても消えないものもある
- 残ったコストも許容範囲内であることが多い
また、現代のハードニングされたC++アプローチとも比較しており、ランタイムの挙動としては両者が収束しつつあるが、総合的な保証は依然としてRustの方が強力だと論じている。
3. LLVMの挙動が非常に重要
興味深いテーマの一つは、パフォーマンスの話は「Rust対C++」というより、「どのLLVMパスが走ったか」という議論になりがちな点だ。
- コールドスプリッティングは行われたか?
- シンボルのローカライズは起きたか?
- 境界チェックは畳み込まれたか?
- パニックのパスは分離されたか?
- インライン展開は適切なタイミングで行われたか?
著者たちはこれらの影響を調査するために、独自のコンパイラパッチや実験を行っている。
4. Rustの人間工学がピークパフォーマンスと競合することがある
Rustの設計が、時として以下のような方向へ誘導してしまうケースにも触れている:
- 余分な初期化
- 不自然な自己参照構造体
- イテレータの複雑さ
- 隠れたパニックパス
- 余分な分岐
これらは致命的ではないが、注意が必要だ。
- 包括的な範囲指定の癖
- MaybeUninitの境界ケース
- 境界チェックの下げ
- コールドパスの配置
- パニックによる命令キャッシュの汚染
などが例として挙げられている。
5. 非常に包括的なレポジトリ
単に「Rust速いぜ」という話じゃない。
- ベンチマークハーネス、コンパイラの計測、LLVMのIssueへのリンク、Godboltの例、アセンブリ分析、証明リンク、コンパイラパッチ、マイクロベンチマーク、ランタイムチェックの切り替えスイッチなどが含まれている。
要するに:
Rustのパフォーマンスを大学院レベルで徹底的にフォレンジック調査したらどうなるか?
要約(TL;DR)
一言でまとめると:
- Rustのパフォーマンスは通常素晴らしく、C++に近い。
- 安全性機能にはコストがあるが、多くは最適化で消える。
- 構造上避けられないコストもある。
- LLVMの最適化品質が結果を大きく左右する。
- パニックやランタイムチェックのコード生成は意外と重要。
- 「ゼロコスト抽象化」は方向性としては正しいが、文字通り無料ではない。
- 思想論ではなく「どこでコストが発生するか」をカタログ化した価値ある資料。
全体的な雰囲気:
Rustはマーケティングのスローガンではなく、真剣なエンジニアリングの精査に値する。
すごいな!プロンプトを代わりに考えてくれるAIを発明したのか
これは最高だね、ありがとう🤩🙏 トークの録画は公開されてる?
ありがとう!トークはロシア語で行われたもので、まだ公開されてないんだ…
やあ、全部読み込めたわけじゃないけど、多くの比較で抜け落ちがちな「本質的なギャップ」を初期段階で指摘してくれてありがとう。本当に重要なのは、慣用的なコードを書いた時の差だよね。ベンチマークだとコンパイラの性能を測るためにあえて特殊なコードを使うことが多いけど、指摘の通り、ほとんどのケースでは似たようなものだし、重要なのは言語設計そのものだ。それに、あまりに特殊なコードなら、そもそも人が書こうとも思わないものだし、unsafeかどうかさえどうでもよくなるよね。