PHPの連想配列で、キーの有無を確認する

PHP連想配列に多めのデータを詰め込んでみたら異常に遅かった。perlだと3秒くらいの処理に17秒かかる。で、色々調べてみたが実用コードとベンチマークで順位が逆転する場合があったりして、どう書くのが最適なのかまだよくわからない。

  • @$ary[$key] よりは isset($ary[$key])の方が早い。ただしどちらも特殊な値ではウソを返す
  • array_key_exists() はコードによって早くなったり遅くなったりする。単純なコードでは速いが実用コードだと遅い?
<?php

function test($size,$find){
	$a=array();
	for($i=0;$i<$size;++$i) $a[ mt_rand(0,$size-1) ] = TRUE;
	$n = 0;
	$before = microtime(TRUE);
	for($i=0;$i<$find;++$i){
		$key = mt_rand(0,$size-1);
		if( @$a[ $key] ) $n = $a[$key];
	}
	$time = microtime(TRUE)-$before;
	echo "time=$time find=$find size=$size integer-key\n";
}
function teststr($size,$find){
	$a=array();
	for($i=0;$i<$size;++$i) $a[ "".mt_rand(0,$size-1) ] = TRUE;
	$n = 0;
	$before = microtime(TRUE);
	for($i=0;$i<$find;++$i){
		$key = "".mt_rand(0,$size-1);
		if( @$a[$key] ) $n = $a[$key];
	}
	$time = microtime(TRUE)-$before;
	echo "time=$time find=$find size=$size   str-key\n";
}

function test_ake($size,$find){
	$a=array();
	for($i=0;$i<$size;++$i) $a[ mt_rand(0,$size-1) ] = TRUE;
	$n = 0;
	$before = microtime(TRUE);
	for($i=0;$i<$find;++$i){
		$key = mt_rand(0,$size-1);
		if( array_key_exists( $key,$a ) ) $n = $a[$key];
	}
	$time = microtime(TRUE)-$before;
	echo "time=$time find=$find size=$size array_key_exists\n";
}
function test_iss($size,$find){
	$a=array();
	for($i=0;$i<$size;++$i) $a[ mt_rand(0,$size-1) ] = TRUE;
	$n = 0;
	$before = microtime(TRUE);
	for($i=0;$i<$find;++$i){
		$key = mt_rand(0,$size-1);
		if( isset( $a[$key] ) ) $n = $a[$key];
	}
	$time = microtime(TRUE)-$before;
	echo "time=$time find=$find size=$size isset\n";
}

$try=1000000;
test    (10     ,$try);
test    (100    ,$try);
test    (1000   ,$try);
test    (10000  ,$try);
teststr (10     ,$try);
teststr (100    ,$try);
teststr (1000   ,$try);
teststr (10000  ,$try);
test_ake(10     ,$try);
test_ake(100    ,$try);
test_ake(1000   ,$try);
test_ake(10000  ,$try);
test_iss(10     ,$try);
test_iss(100    ,$try);
test_iss(1000   ,$try);
test_iss(10000  ,$try);

?>