配列の配列 vs. 連想配列
Perlで、ある対となる二つの値を単に保存しておきたいと思った時、配列の配列を作るのと連想配列(ハッシュ)を作るのではどっちが効率がいいだろう、とふと思ったので、ベンチマークしてみた。
予想では、ハッシュ化する処理があるから、連想配列の方が遅いだろうとは思っていたのだけれど。
ベンチマークのソースは以下。仕事でIPアドレスに関係するものを作っていたので、それっぽいものにしてありますが。
#!/usr/bin/perl use strict; use Benchmark; my @alpha = ( ('a'..'z'), '.'); my @ipaddr = (); my @hostname = (); foreach my $c ( 0..10 ) { foreach my $d ( 0..255 ) { push @ipaddr, join( '.', '192.168', $c, $d ); push @hostname, join('', map { $alpha[int(rand(@alpha))] } (0..12) ); } } timethese( 500, { 'array' => sub { my $cnt = 0; my @array = map { [ $_, $hostname[$cnt++] ] } @ipaddr; }, 'hash' => sub { my $cnt = 0; my %hash = map { $_ => $hostname[$cnt++] } @ipaddr; }, } );
で、結果は以下。
Benchmark: timing 500 iterations of array, hash... array: 10 wallclock secs ( 9.53 usr + 0.03 sys = 9.56 CPU) @ 52.30/s (n=500) hash: 11 wallclock secs (10.99 usr + 0.04 sys = 11.03 CPU) @ 45.33/s (n=500)
10%ほど差が出るようですね。もっと差が出ると思ったのですけどね。
後でピンポイントに参照するのでなければ、「配列の配列」の方が効率がいいようです。
まぁ、当たり前か・・・。
#以下、追記。
ちなみに参照する方は、
#!/usr/bin/perl use strict; use Benchmark; my @alpha = ( ('a'..'z'), '.'); my @array = (); my %hash = (); foreach my $c ( 0..10 ) { foreach my $d ( 0..255 ) { my $ipaddr = join( '.', '192.168', $c, $d ); my $hostname = join('', map { $alpha[int(rand(@alpha))] } (0..12) ); push @array, [ $ipaddr, $hostname ]; $hash{$ipaddr} = $hostname; } } timethese( 1000, { 'array' => sub { foreach( @array ) { my $key = $_->[0]; my $val = $_->[1]; } }, 'hash' => sub { while( my( $key, $val ) = each %hash ) { } }, } );
Benchmark: timing 1000 iterations of array, hash... array: 7 wallclock secs ( 6.50 usr + 0.02 sys = 6.52 CPU) @ 153.37/s (n=1000) hash: 7 wallclock secs ( 7.34 usr + 0.02 sys = 7.36 CPU) @ 135.87/s (n=1000)
ホンの少しですが、やはり連想配列の方が遅いようですね。