元ネタ の方にコメントもしてますが..
Perlで2配列の積集合(Intersection)を取る方法を何個か考えたので、Benchmark取ってみた。
use strict;
use warnings;
use Benchmark;
use List::Compare;
use IO::String;
use IO::Scalar;
use Search::Dict;
use List::MoreUtils qw/uniq/;
my @l1 = map { int rand 1000 } 1..1000;
my @l2 = map { int rand 1000 } 1..1000;
timethese(10000, {
q/List::Compare/ => sub {
List::Compare->new(\@l1,\@l2)->get_intersection;
},
q/hash/ => sub {
my %in_l1 = map { $_ => 1 } @l1;
grep { $in_l1{$_} } @l2;
},
q/hash+exists/ => sub {
my %in_l1 = map { $_ => undef } @l1;
grep { exists $in_l1{$_} } @l2;
},
q/IO::String+Search::Dict/ => sub {
my $ios = IO::String->new;
$ios->print($_,"\n") for (uniq sort {$a cmp $b} @l1);
grep { -1 != look $ios, $_ } @l2;
},
q/IO::Scalar+Search::Dict/ => sub {
my $ios = IO::Scalar->new(\my $data);
$ios->print($_,"\n") for (uniq sort {$a cmp $b} @l1);
grep { -1 != look $ios, $_ } @l2;
},
}
);
Search::Dictは二分木検索の実装です。が、辞書ファイルからの検索を目的としてるモジュールのようなので、一旦辞書を作る必要があります。
手元のマシン(PenD 3.20GHz, メモリ3.5GB)での実行結果は、
Benchmark: timing 10000 iterations of IO::Scalar+Search::Dict, IO::String+Search::Dict, List::Compare, hash, hash+exists...
IO::Scalar+Search::Dict: 83 wallclock secs ( 81.27 usr + 0.03 sys = 81.30 CPU) @ 123.01/s (n=10000)
IO::String+Search::Dict: 110 wallclock secs (108.52 usr + 0.02 sys = 108.53 CPU) @ 92.14/s (n=10000)
List::Compare: 167 wallclock secs (166.36 usr + 0.23 sys = 166.59 CPU) @ 60.03/s (n=10000)
hash: 35 wallclock secs ( 34.64 usr + 0.05 sys = 34.69 CPU) @ 288.28/s (n=10000)
hash+exists: 34 wallclock secs ( 33.75 usr + 0.08 sys = 33.83 CPU) @ 295.61/s (n=10000)
やっぱり hash 強いなー。 そして分かりやすさではダントツの List::Compare はスピード面では散々な結果に..





コメントする