Erlang のプロセスメモリを追う その2

memsup

メモリ周りなら id:voluntas さんに Rabbit MQ 見てみると良いとアドバイスを受け発見。
Erlang のメモリ使用量を監視して notify してくれる仕組み(supervisor)。
ユーザーが指定した上限か、物理メモリ上限に近づいたらデータを消していく仕組みに使えそう。

erlang:memory

前回の続きから。insert_op を走らせただけで 11KB プロセスサイズが増えるのはなぜか。
erlang:memory を実行してみて 2 つのことが分かった。

  • process_used のトータルは -92KB と減っている。
  • (全くの別件だが) erl のオプションで +P 134217727 と最大値を設定しているせいで初回におおきくメモリ領域が予約されてしまう模様。
Total (- 1080364952 1080438392) -73KB
process (- 1074445344 1074537304) -91KB
processes_used (- 1074428408 1074521120) -92KB
code (- 3459465 3369768) +89KB
atom_used(- 383597 378330) +5KB

処理毎に memory 使用量を見ていく

ずばり heap が大きくなるところが分かった。 gen_server の State 更新のために record を新規に作り直している部分だ。

set_left(State, Level, Node, Key) ->
    NewState = State#state{left_keys=mutil:lists_set_nth(Level + 1, Key, State#state.left_keys)},
    NewState#state{left=util:lists_set_nth(Level + 1, Node, NewState#state.left)}.

これはしょうがない。

gc

上記のメモリ使用は合法。不要になったメモリは何らかのタイミングで回収されるべき。
明示的に erlang:garbage_collect/1 呼んでみた。
いい感じ。


trapexit の議論によれば

  • そのプロセスが長い事(もしくは永遠に)使われていないが分かっているなら erlang:garbage_collect を明示的に呼ぶ方法論もあり
  • メモリを使いそうな処理には使い捨てプロセスを利用する

のが良いようだ。


garbage_collect は最後の手だと思うので使い捨てプロセスを試してみた。短期的には改善しない。余計にメモリを食う。
しばらく待ったら解放されるのかな。続く。