Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
なぜ Erlang/OTP を使い続けるのか

なぜ Erlang/OTP を使い続けるのか

更新:2017-04-03
作者:@voluntas
バージョン:1.0.6
URL:https://voluntas.github.io/

2017 年 4 月 1 日に行われた Elixir Conf Japan 2017 の発表者用のメモです。

この資料は公開してあります http://bit.ly/naze-erlang なぜあーらんです、なぜあーらん。

概要

Elixir の話は最初に触れるだけであとは Erlang/OTP の話です。またコードも出てきません。じゃぁ何を話すのかというと、実際にいろいろな分野で Erlang/OTP を利用してきた話をします。実際使ってみてどうだったのかというのも話をします。

ただ、残念ながら話ができる内容がかなり少ないため、事例は少ないです。今回紹介する事例は氷山の一角と思って頂ければ。

実際の事例はおきゃくさまから許可が出ているものだけお話しします。ただ中身のお話しは抑え気味でいきます。

また、 Erlang/OTP を全く知らない人向けには話をしません。すごいE本を読んでいて、Erlang/OTP をある程度知っている前提で話をします。 基本的な説明は省略しますのでご了承ください。

話を最後まできいて質問はしにくいと思いますので、随時質問を受け付けますので、気軽に聞いてください。

自己紹介

Twitter は @voluntas というアカウントです。読み方は ぼらんたす とか ぼるんたす とか、なんでもいいです。 時雨堂という会社で自社プロダクト製品の開発をしています。

Erlang/OTP は使い始めてそろそろ 10 年くらいか、その辺です。趣味で Erlang/OTP を書いたことは無く、書いたコードは全て商用利用されています。

主に通信系のミドルウェアが専門で、データベースはさっぱりです。使う側で策定側ではありませんが認証、課金、暗号とかをちまちまと。

Elixir

モダンな文法で書けて素敵。ただ自分の領域では特に必要ないものという認識です。ただお手伝いしている会社の殆どは Elixir を採用しています。

ただ、結局は Erlang VM なので、その辺の知識でのお手伝いがほとんどです。 Elixir も Erlang VM も詳しい人が出てきたら不要になるおっさんです。

Erlang/OTP

当日アドリブで簡単に紹介します

紹介は省略。何か聞きたい人いますか?

そもそも世の中で Erlang/OTP ってどのくらい使われてるのか?

用途が用途なので、公にされていないのが多いというのが印象です。ただでさえ狭い世界なのに公開されていないのは残念な感じです。

一番有名なのは WhatsApp でしょうか。LINE や Riot など、名だたる会社が Erlang/OTP を使っています。

さらに、マニアックな例を紹介するとドイツの公共無線 LAN の認証にも Erlang/OTP は使われています。いろいろなところをほじくり返せば沢山の場所で使われています。

Golang ではダメなのか?

なぜ Golang を利用しないのか?という聞かれることがあります。それに対する回答はこうです。

Erlang/OTP を選択した場合、 90% は Golang で特に問題ないと思う、ただのこり 10 % で使い道がある

Golang は Google が力を入れており、沢山のユーザがいます。そのうち 99 % が Golang で良くなるのかもしれません。

なぜそれでも Erlang/OTP を選択するのか?

最初に結論をお話しさせていただきます。

落ちにくいからです

Erlang/OTP は経験的にも、実績的にも大変落ちにくいです。ということで、やっと本題です。

おっと、前提を書いておきますね。あくまで今回は「ミドルウェアを開発するに当たって」という前提ありきです、ここ忘れないように。

自分にとって Erlang の最大の魅力は適当に書いてもなんとなく動くことです

そして、何より、適当に書いて落ちたとしても、 Erlang VM 自体は落ちません。 ほとんどの場合はその軽量プロセスがクラッシュして終わりです。 他に影響することはほとんどありません。

他の言語だとどうでしょうか、何か問題があったら色々大変な感じです。実際に経験しています。

Erlang はとても開発者に都合良くできています。

適当に書ける

適当に書ける、というのはかなり重要です。自分にとって適当に書けるというのはプロトタイピングしやすいということです。 メッセージパッシングがあるので、とりあえず色々なところを作って最後に組み立てるというのもやりやすいです。

とりあえず適当に書いて、動くモノを作るのにとても向いています。その設計が本当にあっているのかどうかを確認もしやすいです。

適当に書いてスケールする

さらに、おまけがあります。適当に書いてもなんと性能が出ます。これは恐ろしいですね。 適当に書いても落ちにくい上に、スケールするのです。なんて人をダメにする言語なんでしょうか。

例えば ARM サーバ 96 コアでも 8000% 使えます。凄いですね、 Erlang/OTP 。

実際どのくらい落ちにくいの?

自分の経験では数年ほっといて落ちていません。

改修はちまちま入ったとしてもコア機能がころころ変わる製品を書く言語ではないというのもあると思います。

自分設定ミス以外では ErlangVM 自体のメモリーリークや GC バグ以外で落ちたのを経験していません。

ちなみによく落ちる原因は FD 不足です、皆簡単にスケールするからと言ってさくさく TCP 繋ぎすぎて、 FD 不足で落ちます。

コードが短くなる

Erlang/OTP は DSL と呼ばれるくらい特定の分野に特化しています。そのため、その分野で書く場合の便利機能が色々入っています。 なので、コードが短くなるのです。Erlang/OTP で書いたから短くなるのでは無く、 Erlang/OTP の得意分野で書くと短くなるのです。

これは大変大事なので、今日はここを覚えて帰ってください。DSL なので、当たり前ですが。

後から型チェックがなんとなくできる

Erlang の機能的な話をしないと怒られそうなので、そろそろすることにします。 Dialyzer の話です。Dialzyer は後付静的方解析ツールという感じでいいんでしょうか。

型については詳しくないので質問しないでください。言語スキーではなく開発スキーなだけなんです。

Erlang/OTP は型推論といった便利機能が残念ながらコンパイル時にありませんが、なんと後出しじゃんけんの用に後から型をチェックするという機能があります。それが Dialyzer です。

簡単に言えば、実際にその関数の引数と戻り値の型を考えて、実際に戻る型を確認してくれるわけですね、便利ですよね。便利です。

ただし、後付で解析するのでかなり解析が遅いです。1 万行で 1 分あるかないか、くらいです。複雑になればなるほど遅くなります。

なので CI 必須ですので、 CI で回すことにしましょう。

ちなみに、巨大なシステムを作ってる方で遅くて困ってる人は早くして欲しいです。

文法がしょぼい

言語スキーではないので Erlang の文法の話は余り興味ないのですが、ちょっとくらいは触れておきます。 Erlang はなんといても文法がしょぼいです、たいしたことないです。それが一番の魅力です。

ただまぁ、今日来ていらっしゃる方は Elixir が好きな方だとおもうので、この辺は同意してもらいにくいかもしれません。

しょぼいってのは覚えやすいんです、ただまぁ面白くがないというのは同意です。文法的には Python や Lua が好きです。 あ、 Golang は興味ないですが仕事として書くなら良いと思います。

ビルドツールがある

これ、最近の話なのでなんともですが。昔話をすると老害扱いされますが、昔は rebar3 はなかったんです。ビルドツールなんかなくて、凄い大変だったんです。Makefile がんばって書いてたんです。

今は rebar3 があることで、とても楽になりました。ほとんど気にすることビルドからパッケージングまでできますし、テストや Dialyzer もさくさくっといけます。

パッケージングがある

これ、明らかに Golang の方が 1 バイナリにできるので微妙なんですが、 ErlangVM をインクルードしたパッケージを作れます。 rebar3 があればさくっと作れます。tar.gz で固めれば 20M 位のファイルができあがります。

tar.gz を解凍して /bin/<app-name> start でさくっと動かせるパッケージが作れます。

パターンマッチ万歳

パターンマッチの無い世界でやっていく自信がありません。特にバイナリパターンマッチ最高です。

エンドツーエンドテストが書きやすい

アプリを起動した状態で、クライアントから本当に UDP 投げたり、WebSocket はったりするテストが書きやすいです。 さらにカバレッジも気軽に取れます。

基本的にテストはエンドツーエンドしか信じてないですし、モックはキライです。

軽量プロセスが独立しているのと、同時にいろいろなテストを実行するのも、軽量スレッドがあればさくさくいけます。

ちなみにテストを並列に動かすことも簡単です。テスト時間を短くしやすいです。

マイナー言語なので目立ちやすい

マイナー言語万歳。Erlang/OTP を商用で 10 年やってるひと、ほとんどいません。マイナー言語+商用利用、これを盾にご飯を食べることもできます。マイナーも長年やって実績だしてればご飯食べられます。

最近で、話せる仕事だと建機のオークションシステムを作る仕事をしたりしました。これは Erlang/OTP で商用経験がなかったらできなかったでしょう。

マイナー言語を趣味でやる人は沢山いますが、ここに商用でやってさらにアウトプットとなると、ご飯を食べて行きやすくなります。

ただまぁ、かなり運の要素が多いのでなんとも言えないというのが正直なところです。

軽量プロセスのコントロール

さて、色々 Erlang/OTP の話をしましたが、もうすこし深掘りして話をしてこうと思います。

軽量プロセスは落としやすい

Erlang VM 自体が落ちにくい話は十分しましたが、次は軽量プロセスが落としやすい話をしていこうと思います。

軽量プロセスのお話はどこにでも書いてあるので、今回は軽量プロセスを落としやすい話をしていきます。

ミドルウェアを作ってると、 1 接続に対して複数プロセス (多いときで 10 個程度) を上げることもあります。これらを簡単に連携して、うまく終了するグレイスフルシャットダウン、つまりきれいな終了が実現しやすいです。

link や monitor を使うことで クラッシュ死んだときに検知してどうしたいか を実現できます。 link や monitor についてはすごい E 本を読んで貰えれば十分です。

軽量プロセスをキレイに落とすのは難しい

実は Erlang で一番難しいのは軽量プロセスをうまく終了させるということです。特に 1 軽量プロセスで処理ができればいいですが、 Erlang は遅いので 1 軽量プロセスで処理できる限界が出てきます。

また一時的なタスクで軽量プロセスを上げたりすると、その軽量プロセスの役割が終わったタイミングで軽量プロセスをキレイに終了する必要があります。link つかったりすると連鎖的に一気に死んでしまったりとかもあります。

この辺は今回司会をやってくれてる人がとてもキレイにまとまっているので是非読みましょう。

軽量プロセスキューが詰まると終わる

Erlang VM 最大のはまりどころは軽量プロセスキューが詰まるところです。 Erlang VM の軽量プロセスはキューを持っているため、軽量プロセス内部では順番保証されます。これはとても強いのですが、キューを持っているためキューに処理速度より多くメッセージが遅れてくると死にます。

つまり軽量プロセスが破綻します。経験では 30 万キューまでたまったことがあります。

さて、詰まらないようにするにはどうすればいいのかというと、Erlang VM 内部でシャーディングします。やり方はまぁそんなに難しくないので省略します。

軽量プロセスの性能

echo 処理だとしても 1 軽量プロセスで 10 万メッセージ/秒 は処理できません、大変重要です。これは Erlang VM 自体の性能が上がらないとどうしようもないです。

最近 OTP のお話

さて、最後に Erlang/OTP の今後の話をしようかと思います。

youtube:https://www.youtube.com/watch?v=Ich_G1z44pQ

動画があるのでこれ見るのが一番はやいです。

OTP 20

  • 次の OTP 20 は 2017-06-21 にリリースされます
  • Erlang/OTP は年一回メジャーバージョンが上がります
    • 次が 20 で来年が 21 です
  • atom にユニコードが使えるようになる
  • シグナリングがやっとハンドリングできるようになります
  • ets が 256 以上入った場合、性能が向上します
    • 名前をつけていない ets テーブルの性能が向上
  • IO のスケールの向上
  • やっと #{a => 1, a => 3} でエラーになります
  • string モジュールが unicode 対応
  • SSL で DTLS API が実験的に入る
  • OTP の内部ライブラリが分割される
    • 殆どの人が使わなさそうなのが外に出ます
    • 必要になったら rebar3 で引っ張るような形になります
    • コアを小さくして、必要なものだけを利用するという形にしていく

長期的なお話

  • ファイル読み込みとかネットワークとかの NIF を書き換える
    • ふるいー言語なので、いろいろ負債がある
  • 分散機能を 100 ノード以上へ
  • OTP のライブラリを分割する
  • コンテナやマイクロサービスに優しくしていく
  • JIT

おまけ

ets の delete が早くなるらしいです、嬉しい

https://twitter.com/garazdawi/status/842366257743704065

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment