Java 開発者が Rust に入門してみた#ADC2022髙市 智章 (Tomoaki Takaichi)Nov, 25, 2022 AItech Developer Conference 2022
View Slide
自己紹介@Takaichi00tomoaki.takaichi.5・髙市 智章(タカイチ トモアキ)・2022/05 CA 入社・エレベーターサイネージ・Rust / Java でのシステム開発共著: クリーンなコードへのSonarQube即効活用術www.amazon.co.jp/dp/B086ML43DH
発表の流れ
❏ 主に Java を使ってきた自分にとって、Rust は今までにない概念が多く、つまずいたポイントがいくつもあった (今でもつまずき続けている)❏ Rust を始める6ヶ月前の自分に対して、「Rust はこんな言語ですよ」「Rust と Java はこんな違いがありますよ」と伝えるような発表をコンセプトにし、これから Rust を触ってみようという方の参考になれば発表をしようと思ったか
Rust 言語とは
❏ 2015年に正式リリース❏ 静的型付け・コンパイラ言語❏ システムプログラミング言語❏ C / C++ に匹敵する速度を実現し、OS, 組み込み, ブラウザなど低レイヤーを目的に作られた❏ C 言語に加えて、Linux カーネルの開発向けプログラミング言語として採用される (Linux 6.1 から)Rust 言語
Rust 言語❏ しかしモダンな言語機能も搭載されており、高レイヤーまであつかうことができる❏ 2019年の Rust Survey によると、利用事例が一番多いのは”Web バックエンドアプリケーション” となっている出典: https://blog.rust-lang.org/2020/04/17/Rust-survey-2019.html
Rust 言語の特徴❏ GC (ガベージコレクション) がない❏ にも関わらず、メモリ安全+並行処理安全である❏ ゼロコスト抽象化❏ プログラミング言語が持つ抽象化 (ポリモーフィズム・高階関数 など) の機能をきる限り実行時ではなくコンパイル時に行うことで、実行速度の低下やメモリ使用量の増加を防ぐことができる❏ 独自の仮想マシン (JVM など) を持たず、直接機械語にコンパイルされる
(軽く)Java 言語とは
Java 言語とは❏ 1996年に最初のバージョンがリリースされる (Rust 誕生の19年前!)❏ 静的ページが主流だった当時、Java Applet を使えば簡単に動的ページが作れるというところから人気を博す❏ バイトコードにコンパイル → JVM がインタプリタ実行❏ プラットフォームに依存しないプログラム開発❏ GC / JIT コンパイラ がある❏ エンタープライズシステムなどの利用例が豊富
ここまでの説明を聞いた当時の感想
Rust のファーストインプレッションよくわからないけど、Java より早くて C 言語より安全、モダンな言語機能もあるしバックエンドでもよく使われている。なんか行けそうな気がする!… でも、商用システムで使って大丈夫なの...?
Rust で Web バックエンドアプリケーションを開発してみた
(Java 以外の経験が少ない自分が)Rust でつまずいたポイント
基本文法でつまずく
Rust と関数型言語❏ Rust は関数型言語ではないが、関数型言語由来の文法や言語機能が多く採用されている❏ これからお話する Result, Option, Iterator は関数型の機能 が元となっているが、慣れるまではコードを見ても何が起きているのかイメージしづらかった
Result ・Option 型❏ Rust には Go と同様に例外の機構はない❏ エラーハンドリングには Result という列挙型 (関数型の Either がベース) を使うか、パニックを起こして処理を強制終了させる方法がある❏ 想定内のエラーであれば Result の Err を返すのが基本❏ Rust には null 機能が存在しない❏ これは安全性向上のための意図的な設計❏ 存在するかしないかの値を表現したいときは Option という列挙型を利用する
Result 型・Option 型と match 式❏ Rust にはマッチしたパターンに応じてコードを実行させてくれる強力な match 式があり、Result ・Option 型のハンドリングもやろうと思えばすべて match 式で対応することができる❏ 最初の頃はひたすら match 式で対応していたが、シンタックスシュガーを使いましょうとよく指摘されるTODO: サンプルコード
Result・Option 型 と シンタックスシュガー❏ Result や Option 型は match 式以外にも様々なシンタックスシュガーを用いてハンドリングをすることができる❏ しかし使いこなすまでには時間がかかった (今もなお苦戦中)? 演算子
Result + Option と Iterator の組み合わせ❏ Rust には Java でいう Stream API のような、Iterator というTrait が提供されている❏ Iterator と Option, Result 型などが組み合わさった処理は自分で書けるようになるまで更に時間がかかった
基本文法でつまずく~関数型に慣れる必要がある~
Rust 特有の概念でつまずく
「GC がない」 かつ 「メモリ安全」❏ Rust には GC がないため、メモリ安全のコードを自前で実装しなければならない❏ ただ Rust では「ライフタイム」「所有権」「借用」という仕組みを使うことで、メモリ安全ではないコードはコンパイルを通さないというアプローチをしている❏ これにより、メモリ安全 + 高速な実行速度を実現している❏ 多くの開発者はここに難しさを感じている❏ 2020年の Rust Survey では、ライフタイム, 所有権・借用が Rust で難しいトピックの上位を占めていた
所有権※ 今回は概略だけご説明します
所有権❏ 所有権のルールは以下❏ Rust の各値は、所有者と呼ばれる変数と対応している❏ いかなるときも所有者は1つ❏ 所有者がスコープから外れたら、値は破棄される
所有権❏ 下記のコードは所有権が起因でコンパイルエラーになる代表例
所有権❏ 関数に値を渡しても所有権が移り、下記コードはコンパイルエラーになる
所有権と借用❏ いちいち関数に値を渡すたびに所有権がなくなるのは不便❏ 関数に参照を渡すことで対応することができる (借用という)
所有権と Clone❏ 借用の他にも、Clone という値を複製するメソッドを使うことでも所有権をそのままにすることができる
どのように所有権と向き合うか❏ 何も意識せずに実装していくと、所有権が既に無いなどでよくコンパイラに怒られる❏ 所有権の問題解決の勘所を押さえる❏ 値を参照するだけであれば、参照を渡す❏ Clone トレイトを用いて値を複製する❏ メモリコストはかかるが、そこまでシビアに意識する必要が無ければこの方法で対応することが多い
ライフタイム※ 今回は概略だけご説明します
ライフタイム❏ ライフタイムとは、その参照が有効になるスコープのこと❏ ライフタイムという仕組みによって、ダングリング参照 (解放済みの意図しないデータ参照など) を回避することができる
❏ Rust コンパイラには、スコープを比較して全ての借用が有効であるかを決定する借用チェッカーというものがあり、これのおかげでダングリング参照をコンパイル時に弾いているライフタイム
❏ 下記のコードは、実行するまで x と y のどちらの参照が戻り値の参照となるかわからない❏ x と y のどちらのライフタイムが戻り値となるかコンパイラはわからないためエラーになるライフタイム ~ 変数のスコープが切れない関数 ~
ライフタイム ~ 変数のスコープが切れない関数 ~
❏ 下記の用にライフタイム注釈をつけることで、コンパイラは xと y の短い方のライフタイムを適用するということを知ることができ、コンパイルが通るライフタイム注釈
ライフタイム注釈
どのようにライフタイムと向き合うか❏ ライフタイムは正直難しい... が、なるべくライフタイム注釈を利用しなくても済むような設計を心がける❏ どうしてもライフタイムを意識して実装しなければならない場所は限られてくる❏ ⇒ 要するにブロック内で変数のスコープが完結しない場合(関数で戻り値に参照を使う場合など)❏ 基本的にはブロック内で変数を完結させるようにする❏ できない場合は Clone で複製したり別の Struct を返すようにする
Rust 特有の概念でつまずく~存在を認知して、コンパイラに怒られながら進める~
Web アプリケーション開発でつまずく
❏ Rust のライブラリ (Crate) 開発は活発ではあるが、比較的近年登場した言語のため、デファクトスタンダードがわからず、ライブラリ選定やテスティング手法で時間をかけることが多いと感じる❏ オニオンアーキテクチャなどで DI をしたい場合、Java は Spring の強力な DI の仕組みに乗っかればいいが、今回採用した Rust の Webフレームワークである axum には汎用的な DI がなかったため、DI の仕組みを自作することにWeb アプリケーション開発でつまずく※ 時間の関係で詳しくはご説明できませんが、別途公開する資料や、サンプルコードなどをご覧になってみてください!
Rust を触りたての頃の感想
Java が恋しい!Java なら簡単なのに!Result,Option,iterator…ライフタイム所有権借用…DI の自作ライブラリ選定テスティング
はたして本当にJava のほうが簡単なのだろうか?
Java は Java で難しい部分がある
Java の難しいところ ~ コンテナ化例❏ 例えばコンテナ化をする際、Java では JVM という仕組みがあるため以下のようなことを考慮する必要がある● 起動時間を短くする工夫● コンテナサイズを小さくする工夫● コンテナ特有の JVM パラメータチューニング (GC どうするか、メモリ領域をそれぞれどれくらい取ればいいか...など)● JIT が十分にされていないとスループットが上がらないが、どれくらい暖気をすればいいのか...※ Java でも GraalVM の Native Image を用いて実行可能ファイルを生成できるが 、機能が制限されたりコンパイル時間がとても長かったりと商用利用するには課題も多い
Rust と Java のトレードオフ❏ 実装の容易さという観点だけで見れば、Rust は Java よりも難易度は高く、開発生産性は Java のほうが高いかもしれない❏ しかし運用という観点も含めると、Java は JVM のチューニングやコンテナ化の工夫などが必須で、この分野は体系だった文献も少なく難易度は高い❏ 加えて、LTS・ディストリビューション・サポート...など実際に運用するにあたっては考慮することが多い❏ 一方 Rust はこのあたりを考慮する必要が Java に比べると圧倒的に少ない
Rust と Java のトレードオフ❏ パフォーマンスがある程度要求される場合での、実装と運用の学習コストの個人的な体感❏ 「Rust は難しい」とよく言われている部分は実装難易度の部分が多いのでは❏ ちゃんと運用のことも考えるとJava の学習コストは結構高い
Rust と Java のトレードオフRust Java実行速度・起動速度のチューニング ◯ ✕運用の難易度 ◯ ✕コンテナ化 ◯ ✕実装速度 ✕ ◯ライブラリ・ツールの成熟度 ✕ ◯開発者の確保のしやすさ ✕ ◯❏ 個人的に感じる Rust と Java のトレードオフの関係の一例※ 対比のため ✕ としているが全く向いていないということではなく、それぞれの言語で日々改善が行われている
Java 開発者が Rust で開発してみた~まとめ~
❏ 色々つまづきながらではあるが、Rust でも商用レベルのバックエンドの Web アプリケーションは実装できる❏ Rust 特有の概念の理解や、実装のコツなどの学習コストは確かに低くはないが、その学習コストに見合うだけのメリットは教授できる❏ 一部ツールなどで商用利用を開始しているが、Scala で実装された同機能よりも早い実行速度を実現できているRust でも Web アプリケーションは実装できた
❏ 学習コストに対してパフォーマンスの恩恵が大きい → Rust❏ ある程度のパフォーマンスが求められ、安定したチームで開発・運用し、学習の時間を確保できる場合は特に有効なのでは❏ 今回のシステムでは上記を満たしていたので、Rust の技術選定は納得感が高い❏ (自分の場合) 下記の条件下では使い慣れている Java を選択するかも❏ チームが流動的❏ 期限がシビアかつパフォーマンスがそれほど求められないRust と Java まとめ
学習方法・参考文献
出典: https://m.media-amazon.com/images/I/51Ks0DPW-oL.jpg参考文献 ~ 本出典: https://m.media-amazon.com/images/P/B07TQL7BB9.01._SCLZZZZZZZ_SX500_.jpg● 原典が日本語で読みやすい● Rust とはどういう言語か、CLI, 組み込み, WebAP などの実装例を体系的に学べる● Rust のより詳細な言語仕様や実装方法について学ぶことができる
参考文献 ~ Web● Rust Playground: https://play.rust-lang.org/○ Web 上でコードを書いて簡単に実行できる● Rust ツアー: https://tourofrust.com/chapter_1_ja.html○ Web 上で基本文法を学べる● 公式ドキュメント: https://doc.rust-jp.rs/book-ja/○ 困ったときにはまずここを見る● Rust CookBook: https://uma0317.github.io/rust-cookbook-ja/about.html○ Rust での色々な実装例が記されている● awesome-rust: https://github.com/rust-unofficial/awesome-rust○ 用途に応じてどの Crate を使ったらいいかを非公式にリスト化しているもの○ ORM にはどんな Crate があるか? といった探し方ができる● 元 CA の豊田さんによるハンズオン資料:https://speakerdeck.com/helloyuk13/di-1hui-rust-hands-on-2b580ec5-fdd8-4210-bc6b-ff0549a1945d● 業務で作った Rust ハンズオン: https://github.com/shoichi1023/rust-web-handson
❏ コンパイラに教えてもらう❏ rust-analyzer に教えてもらう❏ IDE 上で Rust の入力補完や文法ミスなどをサポート学習方法 ~ コンパイラと rust-analyzer ~コンパイラや rust-analyzer が表示するメッセージはわかりやすく、時には解決策も提示してくれる
さいごにみなさんもぜひ Rust を使いましょう!!そして情報発信していただけると嬉しいです!!