Hatena::Grouperlang

weekend erlang programmer

ここの更新は止まってしまいました。面倒なので全部kuenishiの日記に書くことにしました。
 | 

{2009, 5, 17}

atom上限数とその考え方 - hoge_to_atom is strongly discouraged - 16:58 はてなブックマーク - atom上限数とその考え方 - hoge_to_atom is strongly discouraged -  - weekend erlang programmer atom上限数とその考え方 - hoge_to_atom is strongly discouraged -  - weekend erlang programmer のブックマークコメント

erlangでは、Rubyにおけるシンボル(:hogeみたいなやつ)と同じ考え方で、決まった名前を参照する際に文字列マッチングとか面倒くさいとかそういうことのためにatomというやつがある。関数型言語では結構使われている。シンボルの数を制限することによってある固定されたメモリ空間に固め置きすることによってアクセス速度とかメモリ管理計算の節約をしているので、atomを動的にいじるのはオススメしないよという話です。ましてやatomを作りまくるなんてあり得ない。あり得ないんだって。

The Erlang VM stores all the atoms defined in all the modules in a global atom table. There is a maximum number of atoms that each VM can store. The upper limit by default is atom_tab (max=1048576).This means the VM can only handle a total of 1048576 different atoms. This should be quite enough in any normal system. It is possible to reach this number if you use Dynamic Atoms. This happens when you dynamically constructs atoms by using the list_to_atom function. It is strongly discouraged to use this.

Erlang Community - Atom Table - Trapexit

上限値は、せいぜい1M個とのこと。つーか、1048576ってマジックナンバーなのかな。せめてマクロとかにしてほしいけど、値を変更しないという強い意志の現れなんでしょうか。atomの考え方として、静的に定義・処理することによって高速化する、というのがありますから、まあ、あながち間違ってはいないんでしょうけど。試してみた人もいるみたいです:

run(N) ->
    if (N rem 1000) =:= 0 -> io:fwrite("~p\n", [N]);
       true -> ok
    end,
    case catch list_to_atom("a" ++ integer_to_list(N)) of
        A when is_atom(A) -> run(N+1);
        Other -> {Other,N}
    end.

Printed 947000 before it crashes.

[erlang-questions] atom table limit & erlang shell

こういう肝心なことってerlang docsのどこかに書いてあったりするんだろか。つーか、あのドキュメントは構造がすごく読みにくい。

追記:検証してもらいました

id:Voluntasの検証では、1040000程度でVMがcrashしたそうです。粘ることなく、潔くcrashするというのは、

  • atomが異常に増加したという状態は、bus errorやSIGSEGVと同レベルの重大な事態だという考え方
  • なので、潔く武士道に則って死ぬ*1

という考え方のようですね。id:Voluntasさん、ありがとうございました。

とはいえ、hoge_to_atomを使う場合ってあんましないので、あんまし関係ないというか、それくらいの使い方しかしないと見込んで(割り切って)こういう設計にしてるんですね。なるほど。。

*1武士道プログラミングプロセスのエラーに対する考え方だけど、VMに対しても同様の考え方がされているという認識か?

VoluntasVoluntas2009/05/17 17:15256 * 256 * 16 = 1048576 っぽいですね。

VoluntasVoluntas2009/05/17 17:21かなり気になってきたので、自宅の開発サーバでやってみます。

kuenishikuenishi2009/05/17 17:25おおお。結果報告よろしくです!
2^nなのはたまたまというかキリがいいってだけの理由なんでしょうね。

VoluntasVoluntas2009/05/17 17:32上の値実行してみたら ...

1040000

Crash dump was written to: erl_crash.dump
no more index entries in atom_tab (max=1048576)
Aborted

erlang vm 落ちてますね。

kuenishikuenishi2009/05/17 17:46おおっ。本文に追記しました。

mikage_sawatarimikage_sawatari2009/05/18 22:53atomの制限はここに書いてありますね.
http://www.erlang.org/doc/efficiency_guide/advanced.html#9.2

手元で限界のコードを試すとなぜかSEGVします.何でだろう…

ATOMの最大値は erts/emulator/beam/erl_term.h で定義されてますね.
この定義を見ると20bitよりもっといけそうに見えるのですが…
32bit環境で 32bit - 6bit = 26bit,64bit環境で 64bit - 6bit = 58bit くらいは使えそうですけどねぇ.
実際にそこまで使う人がいないのでテストされていないのかも.

ドキュメントではIntegerのサイズの記載もありますが,これも古いですしね.
64bitの場合はもうちょっと大きなサイズまで1wordでいけるようです.

kuenishikuenishi2009/05/23 08:05なるほど。それにメモリ制限も加えればちょうどいいのかも、ですね。1word x 1M = 4MBくらい?90年代のハードウェアなら、これが標準サイズなのかも(もう感覚が分からない)。テスト済みの値を変更する必要もなかったから、このままということでしょうかね。
ちなみに、ダウンロードできる最古のソース(R6B)を見たらerts/emulator/beam/atom.cにこんなコードがありました。
#define ATOM_SIZE 3000
#define ATOM_LIMIT (1024*1024)
#define ATOM_RATE 100
ホントにこれなのかな。昔は連結リストだったみたいですw

 |