Slide 1

Slide 1 text

Rust Hands-On 次の40年のためのプログラミング言語 第1回

Slide 2

Slide 2 text

自己紹介 Yuki Tw: @helloyuki_ • AI 事業本部所属のテックリード。 • Rust 領域における Next Experts。 • 外部での活動がこれまではメインだった。

Slide 3

Slide 3 text

Rust との出会い • 前職: 信用デリバや金利デリバなどのリスク管理計算機を作るエンジニアだった。 • 言語は Java 8 だった(プライシングエンジンまわりは C++)。 • 金融では大量のスレッドを使用した計算をする。 • Java でのマルチスレッド計算はかなり熟練した技術者でもバグを仕込みやすい。あと GC 、お前な。 • Rust を紹介(というか惜しみなく絶賛)する Googler の記事に出会う。 • 「こうすれば並行処理で苦労しないのに…」と思っていたアイディアが当時自分の中にあった。 • ぶっちゃけ GC なくなってくれない?安定しないんだけど?とちょっと思ってた。 • Rust は自分の思っていたアイディアを言語レベルでサポートしていることを知る。GC もない。 • この言語すごいなと思ってはじめた。

Slide 4

Slide 4 text

今日のゴール • Rust の解決したかったトレードオフを理解する。 • Rust のコンパイラが厳格な理由を理解する。 • どういった言語機能があるかを軽く理解する。 • 実際に環境構築をして Hello, World! する。

Slide 5

Slide 5 text

本日お話し すること • Rust はどのような言語か? • Rust の言語機能 • Rust を実際に動かしてみよう!

Slide 6

Slide 6 text

本日お話し すること • Rust はどのような言語か? • Rust の言語機能 • Rust を実際に動かしてみよう!

Slide 7

Slide 7 text

Rust はどの ような言語 か? • Rust 概要 • 言語の特長 • Rust の速さ • GC とメモリ安全 • ゼロコスト抽象化

Slide 8

Slide 8 text

Rust に どんなイメージがありますか? アンケート!

Slide 9

Slide 9 text

Rust 概要

Slide 10

Slide 10 text

どういう言語なのか? • 2015年にリリースされた新しい言語。 • 一言で言うなら「システムプログラミング言語である」。

Slide 11

Slide 11 text

システムプログラミング言語 • 担当領域が低レイヤーであるということ。 • OS、組み込み機器のファームウェア • コンパイラ、VM • 各種ミドルウェア • ブラウザ

Slide 12

Slide 12 text

しかし… • 言語設計が、モダンな言語機能の全部のせみたいなところがある。 • 特徴的な言語機能については後ほど解説します。 • 高級言語並みに表現力が豊かで快適にプログラミングできる。 • アンケートでは、Web バックエンドへの利用事例が実は多い。

Slide 13

Slide 13 text

2020年のRustの調 査 • Rust は毎年、言語に関するアンケー トを取っている。 • Webバックエンドの利用例が1位。 • 分散システム、組み込みデバイスな どが続く。 • 観測範囲では、仮想通貨やブロック チェーンでの利用例も多く感じる。 https://blog.rust-lang.org/2020/04/17/Rust-survey-2019.htmlより引用。 画像はランキングの一部を切り取り。

Slide 14

Slide 14 text

言語のカテゴライズ • 静的型付き言語。 • 型クラス指向あるいはムーブセマンティクス指向。 • マルチパラダイムプログラミング言語(Scala などが該当する)。 • 書き味は普通の命令型プログラミング言語(C や Java)。 • 関数型プログラミング言語ではない。

Slide 15

Slide 15 text

言語の特長 • 非常に実行速度が速く、パフォーマンスが安定的である。 • GC はないが、メモリ安全・並行処理安全である。 • メモリ安全: ダングリングポインタ、ヌルポインタなどが発生しない。 • 並行処理安全: データ競合が発生しない。 • 速度確保のために実装を歪める必要がない。

Slide 16

Slide 16 text

言語の特長 • 非常に実行速度が速く、パフォーマンスが安定的である。 • GC はないが、メモリ安全・並行処理安全である。 • メモリ安全: ダングリングポインタ、ヌルポインタなどが発生しない。 • 並行処理安全: データ競合が発生しない。 • 速度確保のために実装を歪める必要がない。

Slide 17

Slide 17 text

Rust の速さ ベンチマークゲームズを参考にして知る

Slide 18

Slide 18 text

C, Go, Java, Node.js, PHP, Python3, Swift を 実行速度の速い順に並べ替えてみてください! クイズ

Slide 19

Slide 19 text

Benchmark Games • 今回参考にするサイトは Benchmark Games というサイト。 • https://benchmarksgame-team.pages.debian.net/benchmarksgame/index.html • ここでいう速さとは、純粋にコード自体の実行時間のことを指している。

Slide 20

Slide 20 text

Rust の速さはいかほど? • Go や Java よりもさらに速い。 • C/C++ と並ぶかさらに速い。

Slide 21

Slide 21 text

Rust の速さはいかほど? • Go や Java よりもさらに速い。 • C/C++ と並ぶかさらに速い。

Slide 22

Slide 22 text

Rust の速さはいかほど? • Go や Java よりもさらに速い。 • C/C++ と並ぶかさらに速い。

Slide 23

Slide 23 text

なぜ速いのか? • 直接機械語にコンパイルされるから。 • ランタイムがないから。 • GC がないから。 • …など。

Slide 24

Slide 24 text

その他語られる話として • Rust には GC がない。 • このおかげで、メモリ使用量などの予測が立てやすい。 • GC の気まぐれでパフォーマンスが変わるといった影響を受けにくい。

Slide 25

Slide 25 text

この節のまとめ • Rust は地球上に存在する利用者の多い言語の中では最速の部類に入る。 • Rust の速さの根本要因は C/C++ と似た話になっている。 • GC がないこと。 • VM などを挟まず、機械語に直接コンパイルすること。

Slide 26

Slide 26 text

言語の特長 • 非常に実行速度が速く、パフォーマンスが安定的である。 • GC はないが、メモリ安全・並行処理安全である。 • メモリ安全: ダングリングポインタ、ヌルポインタなどが発生しない。 • 並行処理安全: データ競合が発生しない。 • 速度確保のために実装を歪める必要がない。

Slide 27

Slide 27 text

GC とメモリ安全

Slide 28

Slide 28 text

GC について、知っていることを教 えて下さい! アンケート!

Slide 29

Slide 29 text

GC のメリデメ メリット デメリット • メモリ管理を手動でしなくていい 。 • コード上にメモリ管理に関する追 加のノイズがなくなる。 • 多くのメモリに関する脆弱性は発 生しない。 • など • たとえばMark&SweepならSweep されるまでオブジェクトを解放で きない。 • ときどき一気にメモリが解放され る時間帯が発生し、その間はアプ リケーションが止まる。 • ランタイムを肥大化させやすい。 • など

Slide 30

Slide 30 text

Rust の領域と GC • Rust が担当する領域は、組み込みのファームウェアや OS になる。 • 計算資源が限られた環境で動くという前提がある。 • この制約下では、下記は困る。 • 言語自体がメモリを多く消費する設計になっている。 • ランタイムが大きい。 • フル GC などでアプリケーションを止められる。

Slide 31

Slide 31 text

メモリの手動管理は… • GC は選択肢にのぼらなくなるが、メモリの手動管理をする必要がある。 • 速度は段違いになる。 • メモリの手動管理はUB (Undefined Behaviour) を生みやすくなる。 • C/C++ 製のアプリケーションではよく UB 起因の脆弱性が報告される。 ※ サニタイザなどのツールの力を借りることはもちろんできる。 ※ C++11からはムーブセマンティクスが導入されたが、あれはあれでいくつか課題があった。

Slide 32

Slide 32 text

事例: Chromium Project • Chromium は C++ 製。 • メモリ関係の脆弱性が70%近くを 占める。 • ↓によるとコストは高い評価だが Rust も検討のテーブルに入ってい る。 どちらの画像も https://www.chromium.org/Home/chromium-security/memory-safety より引用

Slide 33

Slide 33 text

Rustの場合はどうしたか • Rust は GC を採用していない。 • Rust は「メモリ安全はコンパイラが検査する」で解決した。 • 「所有権」「ライフタイム」の仕組みで、メモリ安全でないコードはコンパイル時に弾く。 • 「コンパイラが厳しい」理由はここにある。 • この仕組みの裏側には型理論の研究成果が含まれている。 • こうしたメモリ安全・並行処理安全の仕組みは、第2回で詳しく説明する予定。 • 速度面と安全性のトレードオフを打破した。

Slide 34

Slide 34 text

この節のまとめ • 従来の言語では、メモリ安全のために GC を導入した。 • GC の導入は速度を犠牲にした。 • 従来の言語でのメモリの手動管理は、速度は追求できた。 • メモリの手動管理は安全性を犠牲にした。 • Rust はメモリ安全と速度の両立を実現した。

Slide 35

Slide 35 text

この節のまとめ • Rust はメモリ管理をコンパイラが自動で行う。 • メモリ安全でないコードはコンパイルが通らない。 • その分、余計な手間は増えている。 • コンパイルを通すのが難しくなる理由もここにある。 • というか、ソフトウェアを作るってそもそも難しい行為。 • 難しいが、すべてのプログラマが知っておくべき知識が可視化されている。

Slide 36

Slide 36 text

言語の特長 • 非常に実行速度が速く、パフォーマンスが安定的である。 • GC はないが、メモリ安全・並行処理安全である。 • メモリ安全: ダングリングポインタ、ヌルポインタなどが発生しない。 • 並行処理安全: データ競合が発生しない。 • 速度確保のために実装を歪める必要がない。

Slide 37

Slide 37 text

ゼロコスト抽象化

Slide 38

Slide 38 text

ゼロコスト抽象化とは • コードの抽象化を行ったとしても、追加のオーバーヘッドが発生しないこと。 • メモリ使用量が増加しない。 • 実行速度が低下しない。 • Rust における「抽象化」 • 多相性: ジェネリクス(パラメトリック多相)やトレイト(アドホック多相)。 • 高階関数: filter や map、あるいはクロージャを引数にとる関数。 • Future: 並行処理の抽象機構。

Slide 39

Slide 39 text

他のプログラミング言語では • 例: ジェネリクスを使用すると、動的ディスパッチによるオーバーヘッドが発生する。 • 実行時に関数の抽象と実装の紐付けを行う言語がほとんど。 • この方式を採用すると、紐付けを定義するテーブルの分のメモリ使用量が増える。 • 関数を呼び出す度にテーブルから探すので、その分のオーバーヘッドも増える。 • 例: for ループと for 内包表記とラムダは、全部実行速度が違う。 • 同じことを実現したいのに、採る手法によって実行速度が変わること全般を指す。 • いい例は Py …(おっと誰かが来たようだ。 • 全部実行速度が違うので、プログラマは適切な手法を知っていないとすぐオーバーヘッドが発生。

Slide 40

Slide 40 text

ゼロコスト抽象化のよさ • ゼロコスト抽象化のおかげで、下記のことは考慮しなくて良くなる。 • 抽象化すべき箇所で、実行速度を気にしてやめる。 • XXX という手法は速度が落ちる。YYY という手法を使うべき。 • ZZZ を採用すると、メモリ使用量が上がるから、AAA というハックをすべき。 • こういったワークアラウンドこそ、本当の意味での学習コストではないか? • 正直本質的ではない。 • 我々はコンピュータや実装と真正面から向き合いたい。 • ゼロコスト抽象化がないと C++ の代替は目指せないので、とても重要。

Slide 41

Slide 41 text

動的/静的ディスパッチ • 関数等の紐付けが実行時に解決されること。 • 動的型付き言語の大半。ダックタイピングみたいな。 • Java の implements X をしたとき、など。 • 都度解決する&参照のためにテーブルを探すので、遅い。 • ⇔静的ディスパッチ • 静的ディスパッチはコンパイル時に関数等の紐付けを解決すること。

Slide 42

Slide 42 text

Rust では • 基本的に静的ディスパッチが行われる。 • コンパイル時にジェネリクスの紐付けなどの型解決が行われる。 • 実行時には紐付け完了後のコードが走り、実行中に紐付けは行わない。 • あるキーワードを用いれば、動的ディスパッチもできる。

Slide 43

Slide 43 text

この節のまとめ • 従来の言語では、抽象化によるオーバーヘッドの発生が起きることがある。 • Rust では、ゼロコスト抽象化のおかげで、抽象化を妥協しなくてよい。 • 安心してメンテナンス性の高いコードを、速度面で妥協せず書くことができる。

Slide 44

Slide 44 text

言語の特長のまとめ • 非常に実行速度が速く、パフォーマンスが安定的である。 • GC はないが、メモリ安全・並行処理安全である。 • メモリ安全: ダングリングポインタ、ヌルポインタなどが発生しない。 • 並行処理安全: データ競合が発生しない。 • 速度確保のために実装を歪める必要がない。

Slide 45

Slide 45 text

Rust の言語機能 ササッと学ぶ!

Slide 46

Slide 46 text

みなさんの経験したプログラミング言語を教え て下さい アンケート

Slide 47

Slide 47 text

Hello, World

Slide 48

Slide 48 text

Hello, World • fn = 関数定義 • println! = マクロ

Slide 49

Slide 49 text

変数

Slide 50

Slide 50 text

制御構文 • if, for あたりは他の言語と同じように使える。 • Pattern Matching と呼ばれる switch 文の強力版が使える。 • 制御構文はすべて式(expression)な点に注意する。

Slide 51

Slide 51 text

制御構文

Slide 52

Slide 52 text

制御構文

Slide 53

Slide 53 text

制御構文

Slide 54

Slide 54 text

データ型の作り方 • 構造体を用いて新しいデータ型を定義する。 • enum を用いてデータを定義する。

Slide 55

Slide 55 text

データ型の作り方

Slide 56

Slide 56 text

データ型の作り方

Slide 57

Slide 57 text

エラーハンドリング • Result 型を用いた復帰可能なエラーハンドリングを行う。 • panic を用いて修復不能なエラーハンドリングを行う。 • 使い分けがよく議論の的になっている。

Slide 58

Slide 58 text

エラーハンドリング • 実用上は • プログラム自体の想定しないバグであれば panic しておく。 • 想定内のエラーであれば Result でハンドリングする。 • Java とのアナロジーで考えるなら(Rust には例外機構はないことに注意)、 • panic は非検査例外(RuntimeException) • Result は検査例外(Exception)

Slide 59

Slide 59 text

エラーハンドリング

Slide 60

Slide 60 text

エラーハンドリング

Slide 61

Slide 61 text

エラーハンドリング

Slide 62

Slide 62 text

抽象化の仕方 • 「トレイト」がキーワード。 • パラメトリック多相(ジェネリクス) • アドホック多相(型クラス) • 今回は説明しないが、dyn Trait や impl Trait というものもある。

Slide 63

Slide 63 text

パラメトリック多相

Slide 64

Slide 64 text

アドホック多相

Slide 65

Slide 65 text

メモリ管理の仕方 • 所有権、ライフタイム。 • ダングリングポインタを防止できる→安全性の源 • 今回は説明しないがスマートポインタ。

Slide 66

Slide 66 text

所有権

Slide 67

Slide 67 text

所有権

Slide 68

Slide 68 text

ライフタイム

Slide 69

Slide 69 text

ライフタイム

Slide 70

Slide 70 text

Rust のコンパイルエラー • わかりやすくない? • コンパイラの指示通りに直すと、安全で高速なコードが動く! • コンパイラは心強いもうひとりの同僚。

Slide 71

Slide 71 text

マクロ • 基本的には関数みたいなもの。 • メタプログラミングを可能にする。

Slide 72

Slide 72 text

マクロ

Slide 73

Slide 73 text

マクロ

Slide 74

Slide 74 text

マクロ

Slide 75

Slide 75 text

ユニットテスト • ファイル内に書ける。 • `cargo test` で標準で入っていて、それを叩くだけでよい。テストランタイムが不要。

Slide 76

Slide 76 text

ユニットテスト

Slide 77

Slide 77 text

unsafe • 生ポインタを参照できるようになる。 • 標準ライブラリの unsafe 関数を使用できる。 • unsafe キーワード • unsafe fn • unsafe trait • unsafe ブロック • unsafe ブロック内はコンパイラが安全性保証をしない。 • Rust は C/C++ の外部関数を呼び出す機能も持つ。

Slide 78

Slide 78 text

unsafe

Slide 79

Slide 79 text

Rust を実際に動かしてみよう! 今日一番大事!

Slide 80

Slide 80 text

Rust のインストール • https://www.rust-lang.org/ja/tools/install

Slide 81

Slide 81 text

プロジェクトを作る • cargo new hello-rust

Slide 82

Slide 82 text

Hello, World! • cd hello-rust • cargo run

Slide 83

Slide 83 text

エディタどうする? • ご自由にどうぞ。 • 黄金の組み合わせは VSCode に rust-analyzer をインストールすること。 • 今後のハンズオンもそれで行うので、使ってもらえるとトラブルシュートが早くなります。 • rust-analyzer 自体は Vim や Emacs でも使える。 • また、IntelliJ に Rust プラグインがあります。