私は2016年5月のGW明けから、Erlangのコードを書き始めました。
11月あたりからはElixirをメインに触り始めているので、Erlangに触っていたのは約半年程度になります。
感想
Erlangを半年ほど使った感想を書いていきます。
チョロい
つまり言語機能がとても少ないと感じました。
例えば私が読んだErlangの本はすごいE本だけなのですが、全部で30章ある内の9章までで言語機能が大体出揃ってます。
実際、プロジェクトでコードを書き始めましたが、言語機能で困ったことはほぼありませんでした。
私は、言語機能は一番検索し難しい機能だと思っていて、少なくとも言語機能に関しては検索するのではなく、一通り何らかのドキュメントを読んでおかないと始まらないと思っています。
例えば Python で def f(a, b, *c, **d):
と書いてあって「*
と **
って何だ?」と疑問に思った時、[python * **][検索]
とかしても多分まともな結果は出ないでしょう。
なので、最初にドキュメントを読む量が減るという点で、言語機能が少ないというのはとても良いと思っています。
逆に、他の機能、例えばライブラリに関してはその名前で調べればどういう物か分かるし、使っているアルゴリズムに関してもソースさえ読めれば何とかなります。1
そしてソースさえ読めれば、後は既存のコードを読んで分からない部分を調べていくだけで無限に成長できるはずです。
supervisorがつらい
Erlangを使うということは、多分そこそこ要求される可用性が高いのだと思います。
Erlangは、可用性の高いプログラミングをするための仕組みが沢山あるのでマシなのだと思いますが、それでも可用性を高めるために追加のコードを書く必要があります。
特にスーパーバイザーは、開発中に効果を実感できない機能ナンバー1だと思います。
私自身はまだErlangプロダクトの運用を経験したことが無いので、スーパーバイザーツリーを作るメリットがいまいち分かりません。
普通、アプリケーションが落ちたら自動で再起動する仕組みを用意すると思うので、それだと何が困るんだっけぐらいの認識です。
まあもちろん、影響範囲を一部だけに閉じれるとかそういうのは知識では理解してるつもりなので、スーパーバイザーツリーをある程度まともに作っています。
しかしその作業が実感に結びついていないので、「本当にこのコードは必要なのか?」みたいな気分になってちょっと面倒になってきます。
最初にErlangを使う人は、その辺を乗り越えるのがつらいんじゃないかと思います。
スーパーバイザーツリーを考慮しつつ正しく設計するのは本当に難しいと思います。
幸いなことに、今回のプロジェクトではErlangにとても詳しい人が居たので、その人に相談しつつ作ることができました。2
しかしそれでも、スーパーバイザーツリーは3回ぐらい大きく変更しました。
そういう相談できる人が居ない場合、ソース読みまくるか痛い目に会って覚えるかしか無いんじゃないかなという気がします。
これはErlangが難しいというよりは、要求される可用性を満たすコードを書くのが、Erlangを使っていても難しいんじゃないかなと思います。
データ競合がつらい
ETSとプロセスの相性がとても悪いと感じました。
基本的に、プロセスは独立しているので安全にコードが書けると考えます。
途中で値が書き換えられることなんて無いし、処理中に割り込まれることなんて考えません。
ETSはその辺の暗黙の了解を壊します。
しかもマルチスレッドプログラミングと同じで、机上デバッグしないと見つからないというのが本当に怖いです。
今回のプロジェクトでも、最初の方に実装していた機能が、かなり後の方になってデータ競合を起こす可能性があることに気が付きました。
実際に問題が起きたわけではなく、机上デバッグで発見しました。
ETSを直接使う場合は一つ深呼吸して気合を入れ直して使い始めるからまだマシですが、内部的にETSを利用しているライブラリ(具体的にはgproc)を使う場合は、その辺の意識が希薄になるので本当に気を付けた方がいいです。
ETSは可能な限り使わないでおきましょう。
速度的にプロセスに状態を持たせるので問題ないなら、そうするのが一番良いと思います。
パッケージングがつらかった
過去形です。今はもうrebar3
に移行したので問題ないです。
今回のプロジェクトの最初の方はrebar
を使っていたのですが、意味の分からないファイルが大量にあって、本当にErlangのパッケージングは酷いなと思っていました。
昔はもっと酷かったという話なので、その頃は一体どうやってリリースしてたのか不思議でたまりません。
つまりみんなrebar3
を使おう、ということです。
日本語の情報が少ない
これが今回の Erlang 一人 Advent Calendar をやろうと思ったきっかけです。
私は比較的メジャーな言語(C++, C#, Python)を触ってきていたので、日本語の情報が少ないと思うことはあまりありませんでした。
Erlangはそれに比べると本当に情報が無くて、多分Erlangを使うような人は息を吸うような感覚で英語が読めるんだろうなと思っています。
私は英語を読むのに抵抗を感じる人なので、日本語でErlang情報を発信してくれてる人には本当に感謝しています。
特に Qiita の Erlang Advent Calendar シリーズには何度もお世話になりました。
最近の日本語の Erlang 情報ってここに大分集約されてるんじゃないかなと思います。
ということで、私も何か貢献できたらいいなと思って、このAdvent Calendarを考えました。
何を作っていたか
5月からErlangを書き始めていましたが、これはゲーム用のPub/Subエンジンを書いていました。
多分そのうちオープンソースとして公開されると思います。
主に yamionp が設計をして、私が実装をするという感じです。
設計に関しては彼がQiitaに上げています。
実装
Pub/Subエンジン、正直言うと「ちょっと繋がってる奴らとリレーするだけなのに何か難しいことあるの?」みたいな気分だったのですが、実際やってみると本当に大変でした。
特にTCPコネクションとセッションを分けた時点からヤバくなりました。
順序保証をTCPに担保してもらうことができなくなったので、メッセージの順序制御を自前でやる必要が出てきました。
TCP on TCP、つまり TCP 接続を使って TCP のようなプロトコルを実装するみたいなことをやってて、ほんと一体何を作ってるんだろうとよく考えてました。
まあおかげで、例えばTCPじゃなくてUDPを使うとかQUICを使うとかしても、そんなに変更なく動かせるはずなので頑張った甲斐はあるかなと思います。
性能
性能面では、timer
モジュールで詰まった とか UDPで速度が出なかった とかありましたが、それらを解決したら TCP でも UDP でも、送受信合わせて秒間10万メッセージ程度は出るようになりました。
テスト
テストは結構頑張りました。
本体が4000行程度なのに対して、テストコードは4500行程度あります。
テストがでかすぎると思ってある程度共通部分を減らしたのですが、まだこれだけ残っています。
これらのテストには、クラッシュさせて復帰するテストや、Mnesiaを使ってクラスタリングするテストなんかもあります。
Erlang/Elixir書きたい人募集
ついでにリクルートもしておきます。
このPub/Subエンジンは 株式会社gumi で書いています。
私はこの会社の社員ではなく、個人事業主として準委任契約している状態ですが、ほぼ不満なく働けています。
私の部署はゲームそのものの開発をするところではなく、ゲーム用のライブラリ作ったり研究したりする部署です。
そのせいか、部署内には凄い人が多くて、この人達もっと情報発信していけばいいのになーと思ってたりします。
時間管理されてないのをいいことに、大体12時ぐらいに出社して19時ぐらいには帰ってます。
準委任契約はいつ首を切られるか分からないですが、成果さえ出してれば一応大丈夫そうです。
無料で水とかコーラとかコーヒーとかリアルゴールドとか飲めます。
自販機は50円引きで買えます。
コンビニとか行くと「高っ!」とか思って結局社内の自販機で買ったりとかよくあるある。
ちょっと前まで福利厚生が特に無い、小さい会社でお手伝いをしていたのですが、やっぱりこういうのがあると大分癒される感じがあります。
CTOのお言葉によると、今後はElixirも使っていこうとしているみたいです。
制作現場では、新しい技術を追求するために、API サーバー開発言語として、 Elixir を追加する予定です。
ということで、働きたい人がいればQiitaのコメント、Twitterのリプライ、DM等を使って適当に話しかけてきて下さい。相談には乗ります。
まあ、私に採用する権限は無いので、社内の人に「こういう人から相談を受けたよ」って言うぐらいしかできませんけれども。
完走した感想3
Erlang 一人 Advent Calendar、実際やってみるととても大変でした。
始める前からある程度ネタは考えていたのですが、深く掘り下げたりとかはせず「こういうのを書こう」程度のメモを残していただけです。
しかし実際そこから書き起こしていくと、自分で書いている記事に「何でこれがこうなるんだろう?」と疑問を抱き、そこを調べていって、より深い部分の勉強になりました。
例えば improper listの使い道 なんかは、私のメモには「iolist(), iodata(), improper(不適切な)リストについて纏める」としか書かれていません。
この時は「iolist()
に書いてる improper list って使う機会無いよね」ぐらいに思っていて、投稿する数日前からimproper listについて調べ始めたのですが、気がついたらあの記事が出来上がっていました。
他のErlangの記事を読んでいると、ほんとによく調べていて凄いと思っていて、それでふと自分の記事を見返すと「こんなの書いても鼻で笑われるだけだな」と思って、自分が納得するまで調べていた、というのもあります。
後は初日でコメントを貰えたこともあって、Erlangで間違ったことを書けば即座に指摘してくれることが分かったので、安心して(間違ってるかもしれない)記事を書けました。
本当にありがとうございます。
それらのお陰で、今回のアウトプットは本当に勉強になりました。
ここ数年はあまりアウトプットをせず、社内やオフ会で話したりする程度で満足していましたが、やっぱりこういう場でのアウトプットは重要で、ある程度時間を掛けてでもやるべきだなと思いました。
今はElixirを触っているので、今後はElixirの記事を書いていくことになると思います。
ということで、Erlang 一人 Advent Calendar を最後まで見て下さって本当にありがとうございました!