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上にいくつかモジュールがあるのでメモしておく。

参考:
wakaponさんのよく☆ある☆ふつーの備忘帳 - PL_sv_arenaroot PL_sv_root

*1:全てのSVを管理するメカニズム。