Rust布教系ポエムである。
「lol」という名前のOSS爆誕
Raftというのは、クラスタ内でログを同じ順番で複製するためのアルゴリズムである。 今までこのブログでは、Raftについて何度か紹介してきたわけだが、 ついにがっつりと実装する機会に恵まれ、そのコードを公開するに至った。 その「機会」についてはここでは深く触れることはしないが とにかく、「Rustはいいぞ」とだけ言っておく。
https://github.com/akiradeveloper/lol
ライブラリの名前は「lol」といい、これはネットスラングのLaugh and Loudのことかと思う人も多いだろうが、 どちらかというとLeague of Legendに近い。ちなみにおれはこのゲームはプレイしたことがないどころか、実際にはルールすらわからない。
同じくRust製のRaftライブラリはcrates.ioで調べれば何個か出てきて、 その多くはライブラリといいつつも、実際は学習目的のものだったりするのだが、 そうでない本格的なものとしては
- PingCAPのraft-rs: 分散KVSのtikvで使われている
- async-raft: actix-raftをtokioを使うように修正したもの
- raftlog: ドワンゴの分散ファイルシステムfrugalosで使われているもの
があるのだが、作ってみてから気づいたのだが、 これらは3つともほぼ同じ設計をしていて、おれのlolは全く別の設計になってしまっていた。
設計というのはここでは、 抽象化の界面をどこに設定するかという話で、 これらはどれも、抽象の実装として、 ログなどのストレージやスナップショットの管理も要求する。
Raftライブラリの設計で悩ましいのはこのスナップショットの扱いである。 これはRaftの博論にもスナップショットの扱いが設計上悩ましいことは書いてある。
これには、ステートマシンがメモリなのかディスクなのかとか、 ストリーミングでシリアライズ可能なのかとか、ストレージのスナップショットが使えるのかとか さまざまな条件が絡んでくる。 これら3つのライブラリが抽象を大きくとっているのは、これらをがんばって包括するためであると考えられる。
一方でlolは最初から超汎用的に作る気はなく、 ある程度限定した用途や、スナップショットのinstallについてステートのコピー以上に少し 特殊な意味を含んでいたりと、そういった背景を加味して設計が決まっていった。
ざっと作ってから他のライブラリの設計を調査して、 あぁそういう考え方もあったのかとあとで気づいたわけだが、 それはそれとして、公開するからには何かしら自分のライブラリの立ち位置ないしは売りをはっきりさせないと無意味に終わってしまうわけなので、 抽象に「厚い」「薄い」という概念を強引にひねり出した。 彼らの抽象は厚く、おれの抽象は薄いというわけである。
薄い抽象は本当にステートマシンの部分しか抽象化しない。ログなど他の部分はすべてライブラリのコードとして 提供する。これによるメリットは、ライブラリコードが大きいのでその部分は最適化に有利だろうというのと、 抽象がシンプルなので理解しやすいだろうということ。デメリットはスナップショットに関して融通が効きづらいため、 汎用性に乏しいことと、スナップショットに関する処理で性能的にも多少デメリットがあること。 おそらくどちらかが一方的に良い・悪いということではなく、線はど真ん中ではなく少し偏ってるかもしれないが、トレードオフの関係にあると思う。 もし設計にコメントがあれば、Issueでもメールでも議論お待ちしております。
おれは、ソフトウェアも人間も一番大事なのは個性だと思っているので、 小さくとも個性が見つかってしまったのは良かったと思う。
Raftは学習が容易であることを謳っているが、実装が容易であるとは一言も言っていないので、 Raftをがっつり作るにはそれなりの努力が必要になる。 当然、論文も雰囲気で理解レベルではなく、しっかり読み込む必要がある。 最近、RedisRaftなんていうものも出たりと(その実用性はともかく)、 Raftは重要な技術であることは間違いないので、 Raftについて実装するレベルで知ることが出来たのは運が良かった。
Rustはやはり神言語!神言語!神言語!
次にRustを使ってみた感想だが、改めて、Rustは本当に素晴らしい言語であると感じた。 言語も素晴らしいが、エコシステムが素晴らしい。とりわけ、Future周りのエコシステムが最the高であり、 Rustでなければこんなにすっきりとコードを書くことは出来なかった。 正直にいって、チート言語だと思う。
今から4年前に、 おっさんになってもプログラマをする方法 というポエムを書いたわけであるが、 複数スレッドが同時に動き続ける並行プログラムに関して、コンパイラから多くの保証が得られる Rustは、おれは今36歳であり本来ならプログラマを引退している年齢にも関わらず、 こんなおれにもコードを書かせてくれる。ありがとうRust。
30歳を過ぎたらRustを書こう。
https://github.com/fnwiya/japanese-rust-companies
に、Rustを使っている企業の一覧があって(他にもPFNやCADDiが使ってるはず)、 2016年くらいの世界から見ればずいぶんと増えているし、 Rustの採用は着実に進んでいるとはいえるが、まだまだメジャーとはいえない。 おれはGo言語をこの世から消し去りたい。 より普及させるためには、使ってみたというレポートが必要で、 今晩このポエムを書いてるのはその目的でもある。
Rustは本当に良い言語だ。 小さなコードからでよいので、どんどん使っていこう。 おれも自分のコードが完璧にRustを使いこなしてるとは思わないけど、 多少妥協して書いても十分に速いし、妥協して書くならば、そこまで難しい言語ではない。
競技プログラミングの効果、ありました
最後に、「競技プログラミングは実用プログラミングに良い影響を与えるのか?」 だが、これは良い影響を与えると断言出来る。 実際のところ、おれはlolの開発で一回も全方位木DPを解いていないわけだが、 アルゴリズムをシンプルに記述するという能力自体は役に立ったと思う。 競プロはAtCoder水色で止まったまま実情は半引退状態だが、それ以前ならば こんなコードは書かなかっただろうなと思うようなところがある。
もう1つは、武力の上昇。 おれは前から一気にやる能力はそれなりに高かったとは自覚しているが、 競プロをはじめてからの方が、コードを書くぞと決めたときのスイッチが入りやすくなった。 実際にこのソフトウェアも、よちよちとIOが出来て回帰テストのついた初期コードまで1ヶ月、 それから磨き上げを2ヶ月ほどやり、ここまで3ヶ月で出来た。
これは確かなことはいえないが、 ちょっとした実験的なコードが書きたくてそれが百行くらいにはなると思ったときに、 競技プログラマ(おれ自身をこう呼ぶのはガチ勢に悪いとは思うが) はコードを書くことに対して心理的なバリアがぶっ壊れているため、 じゃあやってみるかと手を動かしてしまうことが出来るという話かもしれない。 気づいたらコードが出来上がっていたということが時々あったからだ。
競プロ純粋培養人間についてはおれがそうでないのでよくわからないが、 もともと実用プログラマの人が競技プログラミングをかじってみるのは 確実に良い影響がある。おれもまだ成長出来ると思うから、近々復帰する予定だ。