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
Azure AI Foundryではじめてのマルチエージェントワークフロー
seosoft
0
150
Hypervel - A Coroutine Framework for Laravel Artisans
albertcht
1
110
既存デザインを変更せずにタップ領域を広げる方法
tahia910
1
270
初学者でも今すぐできる、Claude Codeの生産性を10倍上げるTips
s4yuba
14
8.8k
都市をデータで見るってこういうこと PLATEAU属性情報入門
nokonoko1203
1
590
プロダクト志向なエンジニアがもう一歩先の価値を目指すために意識したこと
nealle
0
120
0626 Findy Product Manager LT Night_高田スライド_speaker deck用
mana_takada
0
140
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
50
32k
GraphRAGの仕組みまるわかり
tosuri13
8
530
Node-RED を(HTTP で)つなげる MCP サーバーを作ってみた
highu
0
120
来たるべき 8.0 に備えて React 19 新機能と React Router 固有機能の取捨選択とすり合わせを考える
oukayuka
2
890
Team topologies and the microservice architecture: a synergistic relationship
cer
PRO
0
1.2k
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
5.9k
Become a Pro
speakerdeck
PRO
28
5.4k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
281
13k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.8k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
YesSQL, Process and Tooling at Scale
rocio
173
14k
Faster Mobile Websites
deanohume
307
31k
For a Future-Friendly Web
brad_frost
179
9.8k
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.5k
Build The Right Thing And Hit Your Dates
maggiecrowley
36
2.8k
Building Adaptive Systems
keathley
43
2.6k
Producing Creativity
orderedlist
PRO
346
40k
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の仕様をきちんと理解するには、コンピュータに対する理解が必要 ◦ なぜデータをスタックに置くほうが好ましいのか ▪ ヒープメモリの確保のコスト、キャッシュメモリの動作等 ◦ なぜ動的ディスパッチがあると遅いのか ▪ 仮想関数テーブルの動作原理