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); ?>