Test::LeakTraceの実装を考える
Test::LeakTraceを実装するために,Devel::LeakTrace::Fastのメカニズムを考えてみた。Devel::LeakTrace::Fastの関数名を眺めて考えただけなので,実際の実装とは異なる可能性がある。
Devel::LeakTrace::FastがしていることはSV Arena*1を走査してある区間内で作成されたが開放されなかったSVを出力する,というものだ。おそらく,擬似コードであらわすと以下のようになる。
my %registry; INIT{ for my $sv(@SV_ARENA){ $registry{refaddr $sv}++; } } # ... END{ for my $sv(@SV_ARENA){ if(not exists $registry{refaddr $sv}){ warn("Possibly $sv is leaked.\n"); } } }
実際には,Devel::LeakTrace::Fastは%registry相当のコンテナを自前で実装している。これはPerlのコンテナを利用することでArenaに干渉したくないからだと思われる。
もっとも,リークの検出には他にもいくつかのやり方が考えられる。たとえば,GCで使われるマーク&スイープ法が応用できそうだ。それならば自前のコンテナを用意する必要もない。マークにはsv_flagsの未使用のビットを使ってもいいし,Magicを使ってもいい。
ArenaについてはCPAN上にいくつかモジュールがあるのでメモしておく。