mapっぽくなにか
先日気になったのでどうなのかなーって思って調べた話。(for Perl)
my @array = ( 1..1_000 );
この配列の値をハッシュのkeyにして扱いやすくしてあれこれしていく、っていうを割とやるのですが、 だいたい
my %map = map { $_ => 1 } @array;
とか
my %map; foreach my $id ( @array ) { $map{$id} = 1; }
とかってやってたのですが先日
my %map; @map{@array} = ();
outout が \%map = { 1 => undef, 2 => undef, .... } こう書いた方が速いです、というコメントを見て、こんな書き方できるのかーって思ったのと 本当に速いんですか?って思ったので調べた。
#!/usr/bin/env perl use strict; use warnings; use Time::HiRes qw(gettimeofday tv_interval); my @array = ( 1..1_000 ); { my $t0 = [gettimeofday]; my %map; @map{@array} = (); my $elapsed = tv_interval($t0); print '--@map{@array}--' . "\n"; print $elapsed * 1000 . "\n"; } { my $t0 = [gettimeofday]; my %map = map { $_ => 1 } @array; my $elapsed = tv_interval($t0); print '--map--' . "\n"; print $elapsed * 1000 . "\n"; } { my $t0 = [gettimeofday]; my %map; foreach my $id ( @array ) { $map{$id} = 1; } my $elapsed = tv_interval($t0); print '--foreach--' . "\n"; print $elapsed * 1000 . "\n"; } { my $t0 = [gettimeofday]; my %map; for my $id ( @array ) { $map{$id} = 1; } my $elapsed = tv_interval($t0); print '--for--' . "\n"; print $elapsed * 1000 . "\n"; } 1;
実行結果
1_000_000で実行
$perl sample.pl --@map{@array}-- 740.508 --map-- 1199.097 --foreach-- 639.542 --for-- 650.275
10_000_000 で実行
$perl sample.pl 10_000_000 --@map{@array}-- 11308.191 --map-- 16796.802 --foreach-- 9985.983 --for-- 10101.491
※ foreachとforが定期的にどっちが速いのかわからなくなるのでまた調べた。 一応 perlsyn - perldoc.perl.org
The foreach keyword is actually a synonym for the for keyword, so you can use either
for と foreachはperldocで同義ですよって言われている。 foreachが速いって思ってたんだけどPHPとごっちゃになってるのかな。
[PHP]ループのメモリ使用量と処理速度を比較しました - Qiita
とにかく
foreach = for > @map{@array} > map
の順で速かったので mapより @map{@array} にしたほうが速かった。
ちなみに valueがundefになって速いなら
my %map; foreach my $id ( @array ) { $map{$id} = undef; }
にしたら速くなるのでは?と思ったけどそんなことはなかった。
まあけど、可読性がよくなるという理由以外にmap使わないようにしましょうって話ですね。
ワンライナーかっこいいという理由でmap使いがちでした/(^o^)\おわた