[Elixir][Erlang]connect to remote node

Connecting to remote production node is very useful to debug or observe production.

  • target node
$ elixir --name [your application name]@[your host] --cookie 123 --erl "-kernel inet_dist_listen_min 9001 inet_dist_listen_m 9001" -S mix phoenix.server
  • local node
$ iex --name debug@127.0.0.1 --cookie 123 --remsh [your application name]@[your host]

Sometimes, you should set port forwarding up to connect to target node via a particular node.

References

[Erlang][Elixir]erlyberlyでErlang/Elixirのdebugをサポート

Erlang/Elixirのdebugを楽にするツールを知ったのでメモ。

実行のワンライナーは以下。

$ git clone git@github.com:andytill/erlyberly.git && cd erlyberly && ./mvnw clean compile install assembly:single && java -jar target/*runnable.jar

これが全て終わって、JavaのGUIが表示されたら、例えば以下のようにnodeを指定してアプリを起動します。

$ iex --name "foo@127.0.0.1" -S mix phoenix.server

起動後、Javaで表示されているtarget nodeに “foo@127.0.0.1” を指定。

すると、メモリ使用量とか、諸々を確認することができる以下のような画面を確認できるようになります。

以下は、この簡単なPhoenixアプリケーションに対して実行した時。

Screen Shot 2016-04-16 at 23.48.49

以下は、http_proxyに対して。

Screen Shot 2016-04-16 at 23.59.23

いずれも、BEAM VMのprocessやatomなどのメモリ使用量が計測できてとても良いですね。atomがGCされないので、これが過度に大きいとメモリ圧迫している、とか簡単にわかりますし。あとはfunctionsの名前空間の形もパッと見ることができますね。

https://github.com/andytill/erlyberly#get-the-process-state

にあるように、processの状態を抜くこともできるようです。

ある程度はObserverでも見ることができますが、メモリ使用量をこんな感じでグラフにしてくれるのは解りやすい。Java製。

[Elixir]Structs, String-keyed Maps, Atom-keyed Maps

Elixirの実装を書いている時、データを保持したりする時にStructs、String-keyed Maps、Atom-keyed Mapsのどれを使えばいいかよく悩んでいました。今日も悩んでいて、何かベストプラクティスないかな、と考えていたところ、ちょうど私の考えと同じものがあったのでメモ。

それぞれは以下な感じで書くことができます。

iex> %{a: 1, b: 2}         # atom
iex> %{"a" => 1, "b" => 2} # string
iex> %Sample{a: 1, b: 2}   # Struct

BEAM VMにおいて、atomはCGされません。そのため、どうてきにatomを生成することは良くない、と知っていました。その上で、何が一番妥当なのかなーと思ってたら、以下ページが見つかりました。

https://engineering.appcues.com/2016/02/02/too-many-dicts.html

ルールは以下。

1. Always Use String-Keyed Maps for External Data

2. Convert External Data to Structs ASAP

3. Use Structs in All Other Code

4. Use Structs for Output Data

5. Avoid Using Atom-keyed Maps That Aren’t Structs

6. Use Keyword Lists Only for Function Arguments

Structsで定義していたら、 defprotdefimple する時にそれ用の実装もできますしね。
パッと見ると、動的に生成することのあるデータにはString-keyed Mapsを使う。何かデータを保持してライブラリ外でも使うような場合はさっとStrucsを。atomを使うkeyword listとかStructは残り続ける値として使うとき。

私の感覚と同じでよかった。

[Elixir]PubSub機構をサクッとつくる

Elixirは receive があらかじめ用意されている。そのため、 send で特定のプロセスに送ったメッセージを受け取って、何らかの処理をするというコードが容易にかける。それを使い、PubSubをするコード。

以下の記事を参考にしました。

http://tech.noredink.com/post/141444822213/pubsub-in-30-lines-of-elixir

[Elixir]Keywordの中身はTupleのList

Elixirに置いて、Keyword listはTupleで表現される。

[{a, b}, {c, d}]

なので、

@hw %{
  1 => "hello",
  2 => "world"
}

hw |> Enum.filter(fn {key, _} -> key == 1 end) |> Keyword.values

のようなパイプを書いた時、取得されるのは ["hello"] になる。

ここで、Elixir v1.2.3 の Keyword.valuesの中身を覗いてみると、以下のようにmapを適用した中でTupleからちょうどvalueを取得してListを作って返している。

  @spec values(t) :: [value]
  def values(keywords) when is_list(keywords) do
    :lists.map(fn {_, v} -> v end, keywords)
  end

当初、

[hello: "world", inu: "neko"] # Elixir

しか Keyword 系は使えないと思っていたけれど、Erlangレベルでは

[{hello, "world"}, {inu, "neko"}] # Erlang

なので、Keyword listとみなしてKeyword操作ができるのですね。学びだ。

蛇足だけれど、 Enum.any?/2 と言う、処理の途中で要素が見つかったらtrueを返す用途で使うfunctionも教えてもらった。なるほど。

[Erlang][Elixir]Efficiency Guide User’s GuideでErlang/Elixirを知る

ErlangのEfficiency Guideが役立ったので、メモ。

Erlang/Elixirをやるなら知っておくべきことが多数ありました。
私が読んだのは、version 7.3

http://erlang.org/doc/efficiency_guide/introduction.html

また、

http://erlang.org/doc/efficiency_guide/advanced.html

にはAtomと言った型に対する制限であったり、メモリの制限などのまとまった情報を得ることができます。他、List操作に対する注意ごとや、tail recuesiveにすることの良さなど。

[Elixir][Erlang]listと、filterの使い心地

ErlangもElixirも、 filter を使う操作で簡単に特定の条件に合致した要素だけのリストを作ることができます。ただ、 filter を使わないで簡単に同様な処理を表現する方法が、Erlangだけでしか思いつかなかったです。。

ただ、ここでElixirにおける for を良い感じで使いたい問題があったのでそちらも。

generate List with for syntax

と書いている箇所です。
2つ以上のリストの組み合わせを入力とした処理を書きたい時、書きやすい形で処理を表現できますね。

適材適所。