Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Rustがどんな言語なのか説明する時に考えたこと
Search
Igaguri
October 05, 2019
Programming
0
190
Rustがどんな言語なのか説明する時に考えたこと
Rust Kansai Meetup #5 発表資料
https://rust-kansai.connpass.com/event/148437/
Igaguri
October 05, 2019
Tweet
Share
Other Decks in Programming
See All in Programming
請來的 AI Agent 同事們在寫程式時,怎麼用 pytest 去除各種幻想與盲點
keitheis
0
120
旅行プランAIエージェント開発の裏側
ippo012
2
900
2025 年のコーディングエージェントの現在地とエンジニアの仕事の変化について
azukiazusa1
24
12k
実用的なGOCACHEPROG実装をするために / golang.tokyo #40
mazrean
1
260
AI Coding Agentのセキュリティリスク:PRの自己承認とメルカリの対策
s3h
0
200
もうちょっといいRubyプロファイラを作りたい (2025)
osyoyu
1
430
Namespace and Its Future
tagomoris
6
700
@Environment(\.keyPath)那么好我不允许你们不知道! / atEnvironment keyPath is so good and you should know it!
lovee
0
120
パッケージ設計の黒魔術/Kyoto.go#63
lufia
3
430
HTMLの品質ってなんだっけ? “HTMLクライテリア”の設計と実践
unachang113
4
2.8k
Improving my own Ruby thereafter
sisshiki1969
1
160
MCPとデザインシステムに立脚したデザインと実装の融合
yukukotani
4
1.4k
Featured
See All Featured
Done Done
chrislema
185
16k
Unsuck your backbone
ammeep
671
58k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.9k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
What's in a price? How to price your products and services
michaelherold
246
12k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
Being A Developer After 40
akosma
90
590k
Imperfection Machines: The Place of Print at Facebook
scottboms
268
13k
Designing for humans not robots
tammielis
253
25k
How to Ace a Technical Interview
jacobian
279
23k
The Cost Of JavaScript in 2023
addyosmani
53
8.9k
Transcript
Rustがどんな言語なのか説明する時に 考えたこと Igaguri Rust Kansai Meetup #5
「趣味でRust書いてます」というとありがちなこと Q. 「Rustってどんな言語なん?」 • 答え方には色々ある ◦ コードを見せる ◦ 性質や機能を列挙する ▪
所有権とかがあって、静的型付けで、ネイティブバイナリにコンパイルできて、 …… ◦ どんな所で使われているか ▪ MozillaでFirefoxのレンダリングエンジンの Servoを記述するのに使われている ◦ どんな意図で作られたのか ▪ →本日のメイン
Rustの設計目標(1/4) • https://prev.rust-lang.org/en-US/faq.html のQ&Aに設計目標が掲載されている。 (Rustプロジェクトの目標は)安全であり、並行性をサポートし、実用的なシステムプログラミング言語を設計・実装することである。 Rustが存 在している(作られた)のは、他のプログラミング言語の抽象化と効率性の(両立の)水準が満足できるものではないからである。 特に、 1. 安全性についてあまり考慮されていない
2. 並行性に関するサポートが貧弱 3. 使い方が自然にはわかりにくい 4. リソースを制御する手段があまり提供されていない などの問題点がある。 Rustは上記の問題点を改善して効率的なコードと使いやすい抽象化を両立した選択肢として存在している(作られている)。
Rustの設計目標(2/4) • 想定される使用場面 ◦ (ネットワーク越しに)攻撃者からの攻撃を受けうる、 CPU-boundなソフトウェア ▪ Webブラウザ、画像変換ツール、ゲーム ▪ インターネットに接続される組み込みソフトウェア
• なぜ安全性が必要なのか ◦ インターネットの荒野ではソフトウェアの脆弱性はほぼ確実に犯罪者に利用されるから ▪ 乗っ取り・情報漏洩・ボットネット ◦ 特にメモリ安全性は、破られた時にメモリ内容の漏洩や任意コード実行につながる • なぜ高速性が必要なのか ◦ 早く結果を返すため ◦ リソースを節約するため ◦ 電力を節約するため
Rustの設計目標(3/4) • 既存言語と比べる ◦ 高速性はあるが安全性が不足している言語 ▪ C, C++, アセンブリ ◦
安全性はあるが高速性が不足している言語 ▪ GCを採用するほとんど全ての言語 • Java, C#, Haskell, Go, ……
(補足)具体的なプログラミング言語間の速度差 https://benchmarksgame-team.pages.debian.net/benchmarksgame/which-programs-are-fastest.html CPU-boundなベンチマークの結果が集計されている(対数グラフに注意)
Rustの設計目標(4/4) • 高速性 ↔ 安全性 というトレードオフ ◦ プログラマによるメモリ管理による高速性。安全性について妥協する。 ◦ 実行時にGCを使うことによるメモリ安全性。高速性について妥協する。 •
Rustは高速性と安全性を両立する ◦ 高速性 ↔ 安全性 ↔ 学習コスト という3点間のトレードオフに変形 ▪ 高速性と安全性を取り、学習コストについて妥協する Rustがどのように高速性と安全性を両立しており、そのために新たに何を学ばなければ ならないかということが、Rustの特徴の説明になる
(例) 型チェック戦略 (1/2) • C/C++ ◦ 弱い静的型付け ▪ 型システムは安全性を網羅的に保証せず、未定義動作になるパターンが数多く存在 ◦
(C++) 仮想関数はオプション ▪ 継承による多相性を使わないなら、仮想関数テーブルを経由しないので速い • Java ◦ 強い静的型付け + ダウンキャスト等の実行時チェック ▪ 不正なダウンキャストは例外を出すので、未定義動作にはならない ◦ メソッド呼び出しはデフォルトで動的ディスパッチ ▪ 継承のサポートのために必要 ▪ 不要な場合JITで消去される(が、JIT自体に実行時コストがかかる) • Ruby ◦ 実行時に型タグを検査(いわゆる「動的型付け」) ◦ インスタンス変数もメソッドもテーブル上にある
(例) 型チェック戦略 (2/2) • Rust ◦ 強い静的型付け ▪ コンパイル時に使われている値の型の整合性を保証 ▪
実行時チェックが不要なので高速 ◦ 継承がない ▪ ないので仮想関数テーブルを用意しなくていい ▪ 動的ディスパッチが欲しければトレイトオブジェクトを使用する • Box<dyn T>などに仮想関数テーブルが含まれている
(例) 所有権, 借用, ライフタイム (1/2) • 問題: Double-Free、Use-After-Free等のメモリ管理系の脆弱性 • CやC++での扱い
◦ 変数はスタックとヒープの両方に確保できる ▪ 関数内でしか使わないなら、スタックに置くほうが高速なので嬉しい ◦ プログラマがmalloc / freeを使って管理する ▪ ミスは良くてメモリリーク、悪いと未定義動作を引き起こす ◦ C++には限定的に解決するスマートポインタが存在 • JavaやRubyなどでの扱い ◦ クラスのインスタンスは全て参照経由で扱う ◦ 参照型の参照先になるインスタンスは全てヒープに確保 ◦ プログラムは参照を使い終わったらそのままポイ捨て ◦ GC機構が実行中に参照の有効無効を判定してメモリを回収する ▪ 様々な工夫があるが、それでも実行時コストがかかる
(例) 所有権, 借用, ライフタイム (2/2) • Rustの扱い ◦ 所有権 (ownership)
▪ 値には単一の所有者が存在する ▪ 所有者は自身が開放される時、所有する値を開放する 管理責任を持つ ◦ 借用 (borrowing) ▪ 所有者以外は限定的な操作のみが許され、 freeなどはできない ▪ 可変参照と共有参照の区別がないと、 Use-Afer-Freeを起こせる • Vecの要素への共有参照がある状態で Vecを拡大した場合など ▪ 循環参照を作らせない効果もある ◦ ライフタイム (lifetime) ▪ 借用である参照の期間をチェックする ▪ Use-After-Freeを回避 ownership
(例) 静的に解決されるジェネリクス (1/2) • C ◦ そんなものはない • C++ ◦
コンパイル時に具体的な型のそれぞれについて展開されるテンプレート ▪ 具体的な型が埋め込まれたコードになり、最適化が効きやすく高速 ▪ 型の保証は不十分(展開後のコードが不正な時はコンパイルエラーにはなる) • Java ◦ 具体的な型(メソッド実装)が動的に解決されるジェネリクス ▪ Javaのジェネリクスは型検査後に型消去され Objectクラス扱いになる ▪ インスタンスを使う時は自動的にダウンキャストをして使用 ▪ プリミティブ型が使えないのはこの機構のせい • Ruby ◦ ダックタイピングなのでそもそもジェネリクス機構という概念が存在しない ▪ 実行時にインスタンス変数やメソッドの有無を判定している(遅い)
(例) 静的に解決されるジェネリクス (2/2) • Rust ◦ コンパイル時に具体的な型のそれぞれについて展開されるジェネリクス ▪ C++と同じく、通常のコードに展開されるため最適化が効きやすい ▪
C++と同じく、(T: Sizedなら)スタックに確保できるので速度性能が良い ◦ トレイトを使用して型の範囲を制限できる ▪ 展開前に型エラーを出せるため、エラーメッセージが人間に優しくなる ▪ T::default() のようにトレイトにあるメソッドではない関数も呼び出せる
まとめ & 余談 • まとめ ◦ 設計目標の観点から Rustの特徴を説明するアプローチがある ▪ 高速性と安全性を両立し、そのために導入した機構に関する学習コストを犠牲にしている
◦ Rustの基本的な仕様は、設計目標を達成するように選ばれている ▪ 型、所有権・借用・ライフタイム、ジェネリクスの仕様、継承の排除 …… • Rustの仕様をきちんと理解するには、コンピュータに対する理解が必要 ◦ なぜデータをスタックに置くほうが好ましいのか ▪ ヒープメモリの確保のコスト、キャッシュメモリの動作等 ◦ なぜ動的ディスパッチがあると遅いのか ▪ 仮想関数テーブルの動作原理