%ENVのアクセスは遅い?

今日、お世話になったキールを見にいった。移転すると言うことで、見納めである。
そこで、面白い話を聞いた。%ENVに値を代入するのは遅いと言うのだ。聞いただけでは本当かどうか分からないので、実際にソースを書いてベンチマークを取ってみることにした。
もしも本当に遅いと言うことになれば、ICFPのソースにも大きく影響することになる。

まず用意したのは以下の二つのソースである。

$ENV{hoge} = 1;
for(1..10000000){
    $ENV{hoge}++;
}
%a
$a{hoge} = 1;
for(1..10000000){
    $a{hoge}++;
}

これのベンチマークをtimeコマンドで数回取ってみたところ、
上側は約17秒、下側は約5秒であった。

次に、もう二つソースを用意した。

$ENV{hoge} = {};
$ENV{hoge}->{hoge} = 1;

for(1..10000000){
    $ENV{hoge}->{hoge} = 1;
}
my %a;
$a{hoge} = {};
$a{hoge}->{hoge} = 1;

for(1..10000000){
    $a{hoge}->{hoge} = 1;
}

これだと、どちらも大体7秒くらいで完了した。
すなわち、%ENVに値を代入するときには、実際に環境変数を書き変えているような気がする(setenv関数を呼んでいる?)
これを回避するためには、%ENVを使わないか、もしくは良く書き変える部分は$ENV{hoge}->{hoge}というようにハッシュのハッシュとして使った方が良いだろう。