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
CSC305 Lecture 04
javiergs
PRO
0
270
Writing Better Go: Lessons from 10 Code Reviews
konradreiche
0
780
私達はmodernize packageに夢を見るか feat. go/analysis, go/ast / Go Conference 2025
kaorumuta
2
540
Server Side Kotlin Meetup vol.16: 内部動作を理解して ハイパフォーマンスなサーバサイド Kotlin アプリケーションを書こう
ternbusty
3
180
Things You Thought You Didn’t Need To Care About That Have a Big Impact On Your Job
hollycummins
0
220
『毎日の移動』を支えるGoバックエンド内製開発
yutautsugi
2
240
(Extension DC 2025) Actor境界を越える技術
teamhimeh
1
250
Introducing ReActionView: A new ActionView-Compatible ERB Engine @ Kaigi on Rails 2025, Tokyo, Japan
marcoroth
3
1k
CI_CD「健康診断」のススメ。現場でのボトルネック特定から、健康診断を通じた組織的な改善手法
teamlab
PRO
0
210
kiroとCodexで最高のSpec駆動開発を!!数時間で web3ネイティブなミニゲームを作ってみたよ!
mashharuki
0
140
What's new in Spring Modulith?
olivergierke
1
140
育てるアーキテクチャ:戦い抜くPythonマイクロサービスの設計と進化戦略
fujidomoe
1
170
Featured
See All Featured
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.2k
Leading Effective Engineering Teams in the AI Era
addyosmani
1
26
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Being A Developer After 40
akosma
91
590k
Faster Mobile Websites
deanohume
310
31k
The Language of Interfaces
destraynor
162
25k
The Cult of Friendly URLs
andyhume
79
6.6k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.4k
Designing for humans not robots
tammielis
254
26k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.1k
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の仕様をきちんと理解するには、コンピュータに対する理解が必要 ◦ なぜデータをスタックに置くほうが好ましいのか ▪ ヒープメモリの確保のコスト、キャッシュメモリの動作等 ◦ なぜ動的ディスパッチがあると遅いのか ▪ 仮想関数テーブルの動作原理