Erlang(Elixir)の使いどころについて使ってる人から教わった話

Erlangのことを調べてて気付いたことをつぶやいたら、既に開発で使ってる方からいろいろ教えてもらったのでメモ。
9
t_yano @t_yano

Erlang/Elixir(というかBEAM)について「速い」と記事書くと有識者の方々から暗に殴られる事件を数件見つつ、最近読んだbeamのコンテキストスイッチ手法思い出すと、まあ、この動きすごいキレイ(一定頻度でプリエンプティブにスイッチする)だけど、速くはないわなって思った

2016-05-17 21:15:29
t_yano @t_yano

BEAM決して速くない、速さを求めるならGoをやれ、安定性を求めるならbeamをやれってことみたい。Erlangイカ本だと、バイナリデータを大量に処理するには向かない、でもAPIサーバなら十分な速度が出るって書いてて、つまり個々の「処理」の速さを求めてはいけないってことかな。

2016-05-17 21:17:35
t_yano @t_yano

プリエンプティブなスイッチはキレイだし書く方も楽だけど、(なんならCPU占有できる、協調型マルチタスキングに比べると)速くはないってのは、PC用OSがプリエンプティブマルチプロセスを実装し始めたあたりでも話題になった覚えがある。

2016-05-17 21:19:10
t_yano @t_yano

beamの軽量プロセスの処理、もろに、OSプロセスと同じものを目指してる感あって、プロセスにおける協調型スイッチ→CPUパワーあるからプリエンプティブ(強制)スイッチするわって流れを、スレッド切り替えでやってる感あるんだけど。 そしたら未来には、軽量軽量プロセスの争いが起きるの?

2016-05-17 21:22:17
t_yano @t_yano

より協調型(速いけどデッドロックの可能性がある)からプリエンプティブ(遅いけど確実に切り替わる)に並べると、Clojure(core.async)、Go、Erlang/Elixir ってことなんかな。

2016-05-17 21:23:47
t_yano @t_yano

Clojureのcore.asyncにあるgoブロックは、チャネルのIOだけによってプロセスが切り替わる仕組みなんで、あるチャネルのライトに対して、リードするプロセスが存在しない場合、スタックする可能性がある(しないようなバッファを作ることも出来るけども、用途は限定的)。

2016-05-17 21:25:32
t_yano @t_yano

GoはIO処理で自動切り替えするらしい。おそらく、UNIX/Linuxのselect/epoll/kqueueが発生したらそこで切り替わるってことだと思う。

2016-05-17 21:26:44
t_yano @t_yano

Erlang/Elixir(beam vm)は、組み込み関数はすべて、実行するたび(あるいは途中でも)にreduction budget(「処理予算」とでも訳すか?)を消費する。1回の実行の度に2,000の予算があり、関数呼び出しの度に消費し、使い切ったら強制的に切り替わる。

2016-05-17 21:29:03
t_yano @t_yano

なんか、正規表現ライブラリとかはErlangで書き直されてて、長い正規表現を解釈するときは、解釈途中でも切り替わるようになってるらしい。

2016-05-17 21:30:05
V @voluntas

@t_yano 多分それは読み間違いだと思います。バイナリデータを大量に処理(計算)するのに向いていません。例えば映像のエンコードとか。バイナリデータをパースして処理してビルドするのは全然むいてますよ。あ

2016-05-17 21:31:00
V @voluntas

@t_yano Erlang が遅いというのは主に ets が遅いというのがスタートです。さらにプロセス自体が軽量スレッド(抽象化)されてしまっているので、そのオーバヘッドが大きく性能がでないという感じですね。なので「多くの重く長い処理」に凄く向いてないです。

2016-05-17 21:32:30
V @voluntas

@t_yano ネットワークサーバは基本的には「軽くて大量のバイナリを並列にパースする」というのがミッションになるので、その辺には向いています。ただ ets が遅くなる(といっても数マイクロ程度)タイミングがプロダクションだと出てきます。

2016-05-17 21:33:28
V @voluntas

@t_yano あとは結局 1 プロセスが処理できる性能が圧倒的に低いので遅いんですよね。1 プロセスで秒間 100 万リクエストは絶対裁けないです。これは軽いけど量がひどい場合ですね。これは Erlang はしんどいです。

2016-05-17 21:34:12
V @voluntas

@t_yano Erlang VM 上で上手く分散さえできればまぁ普通なのですが上手く設計するだけでツライので … 。後はそうですね、Golang/Rust のような言語には絶対勝てないです。そもそも VM ベースで JIT も積んでいないので。

2016-05-17 21:35:11
V @voluntas

@t_yano そう冷静に考えると JavaVM はすばらしいわけで、それを無視して Erlang VM 早いはアホかなという感じですね。

2016-05-17 21:35:32
t_yano @t_yano

@voluntas 指摘ありがとうです。個々の「処理」ってので言いたかったのがそんな感じですかねえ。大量の小さな処理を裁くのに向いてて、一つ一つの処理が長くて重いのに向いてない(個々の処理性能を追うものではない)って感じがしてます。まだ勉強中ですが。。。

2016-05-17 21:36:56
Yoichiro Tanaka @yoichiro

@t_yano @voluntas そういう意味じゃあLINEのサーバのGateway部分にErlangを選択したのは、筋は悪くないって感じかな。細かなリクエストをセッション維持しながら裏側に待ってるサーバ群とひたすら橋渡ししていくっていう。

2016-05-17 21:39:09
t_yano @t_yano

今のErlang学習の目標は、最近Elixrをやりたいって言われることが数回あって、向いてるところ向いてないところを自分でちゃんと理解して回答したい(やりたいならそのへんまで興味持ってくれっていう厳しめの意図もある)ってモチベーション。いいなと思ったら自分でも使おうかなってところ

2016-05-17 21:41:17
V @voluntas

@t_yano そうですね。結局計算処理が入ったりするととたんに遅くなります。細かいパケットが「大量に分散」できるのが大事ですね。基本的には交換機、つまり Proxy/Relay に向いている製品だと思います。まぁココの処理が重い場合はもう C/C++ の世界だと思います

2016-05-17 21:42:02
V @voluntas

@yoichiro @t_yano そうですね。あとは横に沢山並べていけるってのもあるので。 @t_yano がおっしゃるとおり、早いとかではなく特定領域で開発効率が高く(DSL なので)、落ちにくい場合に凄く向いています。

2016-05-17 21:43:13
V @voluntas

@t_yano Elixir をやるよりも Phoenix/Ecto をやったほうがいい気がします。基本ウェブアプリだと思いますので、Erlang の内部よりもそのフレームワークの強さかな、と。

2016-05-17 21:43:49
t_yano @t_yano

ところでBEAMってBogdan/Björnʼs Erlang Abstract Machineの略らしく、「抽象マシン(abstract machine)」ってワードが入ってるので、BEAM VMっていうと冗長だと思ってるけど、VM付けないと何の話か分かってもらえない感もある。

2016-05-17 21:44:33
t_yano @t_yano

@voluntas そうですねー私に向けて話に出てくるのはElixirなんですけど、その性能とか向き不向きを考えるには、土台のErlangとBEAMが分からないと話にならなさそうってことで、まずErlangとBEAM追ってる感じです。

2016-05-17 21:46:36
V @voluntas

@t_yano 多分ですが BEAM ってあんまり言わないです(Erlang VM ? って言う方が多い気がします) 。Erlang は軽量スレッドがあって、まぁ非同期やマルチスレッドのワーカーがんばらなくて、まっすぐ書けるくらいで十分だと思います。

2016-05-17 21:47:36
t_yano @t_yano

@voluntas お、BEAMってあんまりいわないんですね。たしかにWikipediaの英語のページでもErlang VMって書いてるんで、おや、とは思っていた。。。

2016-05-17 21:48:27