二つの配列からハッシュを作成するベンチマーク

昔に作ったファイルを見ていて、よくわからないコードが出てきたので調べた。 それは、ハッシュのスライスだった。 未だに覚えられないのは、やはりあまり使わないからだろうなぁ…。 で、なんとなく思いついたので、ハッシュを作成するベンチマークを取ってみた。 何も考えずに書くとループして作るだろうなぁ、という感じのループと、そのループを展開したもの、そしてスライス代入と直接代入の4種類。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Benchmark: running Unroll, direct, for, slice for at least 3 CPU seconds...
Unroll:  2 wallclock secs ( 3.16 usr +  0.00 sys =  3.16 CPU) @ 264160.01/s (n=833689)
direct:  2 wallclock secs ( 3.15 usr +  0.00 sys =  3.15 CPU) @ 287373.38/s (n=906663)
for:  3 wallclock secs ( 3.13 usr +  0.00 sys =  3.13 CPU) @ 174892.19/s (n=546713)
slice:  3 wallclock secs ( 3.00 usr +  0.00 sys =  3.00 CPU) @ 282924.03/s (n=849055)
Rate    for Unroll  slice direct
for    174892/s     --   -34%   -38%   -39%
Unroll 264160/s    51%     --    -7%    -8%
slice  282924/s    62%     7%     --    -2%
direct 287373/s    64%     9%     2%     --

ハッシュを直接書くよりはさすがに遅かったが、それにしても2%しか差がないのは驚き。 これは使わない手はないね。 で、ソースは以下のとおり。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
use strict;
use warnings;
use Benchmark qw(:all);
our @la = (1 .. 5);
our @lb = ('one', 'two', 'three', 'four', 'five');
cmpthese(
timethese(
0, # 0 is auto
{
direct => sub {
my %hash = (
1 => 'one',
2 => 'two',
3 => 'three',
4 => 'four',
5 => 'five',
);
},
for => sub {
my %hash;
for my $i (0 .. 4) {
$hash{$la[$i]} = $lb[$i];
}
},
Unroll => sub {
my %hash;
$hash{$la[0]} = $lb[0];
$hash{$la[1]} = $lb[1];
$hash{$la[2]} = $lb[2];
$hash{$la[3]} = $lb[3];
$hash{$la[4]} = $lb[4];
},
slice => sub {
my %hash;
@hash{@la} = @lb;
},
}
)
);

Comments

comments powered by Disqus