Re: GCと計算量 (Re: GC Re: LISP を使うとき([Q] ログインシェルとそうでないシ ェル))
kono@ie.u-ryukyu.ac.jp (Shinji KONO) writes:
> ううむ... 破壊的append と非破壊的appendではオーダは変わりますよね。
オーダーは同じだと思うなあ。 Lispで言えば (append a b) と (nconc a b)
ですよね。どっちも O(length(a))だと思う。
> free を O(1) にするには、memory pool みたいなのを使うと可能
> です。非破壊append bench mark を別プロセスでやって GC しない
> で抜けて来るみたいな感じ。それが一般的なGCの仮定に反する(自
> 由に参照をコピーできる) のはその通りです。で、そういうことす
> ると GC を持っているシステムでは、まずいってな話でしたよね。
なるほど。RTSJ (Real-time Specification for Java)のRegionみたいに一括
解放するわけね。dangling pointerのチェックもしなくて良いなら、確かに最
速ですね。
しかしですね。以下の条件が満たされるならオーダーは変わんないですよ。
・割り付けた領域には、少なくとも一回データが書き込まれる(初期化でも可)
・ヒープサイズは生きているデータの量に比例して増加させてよい
・GCのルート集合の大きさは、高々生きているデータの量に比例する程度
この条件だと、「Nバイト割り付けて解放する」サイクル全体のコストは、GC
使おうと使うまいとO(N)になりますよね。
実際の話、一括解放でよいプログラムの場合、ある期間に割り付けられたオブ
ジェクトが全部ゴミになるわけですよね。これは、現在よく使われているコピー
式の世代別GC がうまくアジャストできれば、全くコピーしないでGCが終る可
能性があります。この場合、ほとんどコストは変わらないでしょう。コピーGCっ
て結局「dangling pointerにならないようにコピー + 一括解放」ですから。
そう都合良くサイズが合わないで、何回かコピーしちゃったとしても、オーダー
は変わらない。たかだか定数倍。
> 二乗でゴミを吐くプログラムなんてダメダメなのは、その通りなん
> だけど、線形でゴミを出すのは良くありますよね。というか、これ
> までの話だと、むしろ推奨されている。で、そうやって生成したゴ
> ミを回収するコストが、ゴミの量に比例するかって言うと、それは
> アルゴリズムによります。
上のとおりヒープを増加させて良いなら、ゴミの量というか割り付けた量に比
例するコストで回収できます。つまり、1バイトあたりの割り付け+回収のコ
ストは定数オーダー。
前田敦司
Fnews-brouse 1.9(20180406) -- by Mizuno, MWE <mwe@ccsf.jp>
GnuPG Key ID = ECC8A735
GnuPG Key fingerprint = 9BE6 B9E9 55A5 A499 CD51 946E 9BDC 7870 ECC8 A735