ハッシュ生成時のメモリコピー
ハッシュが余りに便利すぎて半笑いなのだけど、性能的にメモリコピーが気になった。
use strict; use warnings; my $str = 'string_hogehoge'; my $hash = { data => 'hash_hogehoge', }; sub hash_from_array { my $arg = {@_}; $arg->{data} = 'changed_in___hash_from_array'; print $arg->{data}."\n"; } sub hash_ref { my $arg = shift; $arg->{data} = 'changed_in___hash_ref'; print $arg->{data}."\n"; } print "====== from array #1=====\n"; hash_from_array( data => $str ); print $str."\n"; print "====== from array #2=====\n"; hash_from_array( data => $hash->{data}, ); print $hash->{data}."\n"; print "======= reference #1 ====\n"; hash_ref( { data => $str, } ); print $str."\n"; print "======= reference #2 ====\n"; hash_ref( $hash); print $hash->{data}."\n";
ハッシュや文字列から無名ハッシュを生成したり、ハッシュのリファレンス渡しをしてみたところ、
$ perl hash.pl ====== from array #1===== changed_in___hash_from_array string_hogehoge ====== from array #2===== changed_in___hash_from_array hash_hogehoge ======= reference #1 ==== changed_in___hash_ref string_hogehoge ======= reference #2 ==== changed_in___hash_ref changed_in___hash_ref
ハッシュのリファレンス渡しをする以外のパターンは、全てコピーが発生しているような気がする。アドレスが見れれば嬉しいのだけど。でもcopy on writeの仕組みがあったりすると上記テストだとわからないんだよなぁ。気になる…
以下のベンチマーク結果からは影響が無いようにも思える…
use strict; use warnings; use Benchmark qw/cmpthese timethese/; my $buf = "A" x (1024*1024); cmpthese( timethese( 0, { normal => sub { hoge_normal ( { data => $buf, }); }, normal_noaccess => sub { hoge_normal_noaccess ( { data => $buf, }); }, normal_nop => sub { hoge_normal ( { data => $buf, }); }, from_array => sub { hoge_from_array ( data => $buf,); }, from_array_noaccess => sub { hoge_from_array_noaccess( data => $buf,); }, from_array_nop => sub { hoge_from_array ( data => $buf,); }, } ) ); sub hoge_normal { my $hash = shift; $hash->{data} .= "Z"; } sub hoge_normal_noaccess { my $hash = shift; } sub hoge_normal_nop {} sub hoge_from_array { my $hash = {@_}; $hash->{data} .= "Z"; } sub hoge_from_array_noaccess { my $hash = {@_}; } sub hoge_from_array_nop {}
全部一緒だ… copy on writeも無さそうだ。全体の負荷に対してメモリコピーの負荷が極小ってことかなぁ…
Benchmark: running from_array, from_array_noaccess, from_array_nop, normal, normal_noaccess, normal_nop for at least 3 CPU seconds... from_array: 3 wallclock secs ( 1.53 usr + 1.47 sys = 3.00 CPU) @ 152.67/s (n=458) from_array_noaccess: 3 wallclock secs ( 1.75 usr + 1.47 sys = 3.22 CPU) @ 152.80/s (n=492) from_array_nop: 3 wallclock secs ( 1.68 usr + 1.46 sys = 3.14 CPU) @ 151.91/s (n=477) normal: 3 wallclock secs ( 1.64 usr + 1.50 sys = 3.14 CPU) @ 151.91/s (n=477) normal_noaccess: 3 wallclock secs ( 1.67 usr + 1.57 sys = 3.24 CPU) @ 152.16/s (n=493) normal_nop: 3 wallclock secs ( 1.66 usr + 1.48 sys = 3.14 CPU) @ 151.91/s (n=477) Rate normal_nop normal from_array_nop normal_noaccess from_array from_array_noaccess normal_nop 152/s -- -0% -0% -0% -0% -1% normal 152/s 0% -- 0% -0% -0% -1% from_array_nop 152/s 0% 0% -- -0% -0% -1% normal_noaccess 152/s 0% 0% 0% -- -0% -0% from_array 153/s 0% 0% 0% 0% -- -0% from_array_noaccess 153/s 1% 1% 1% 0% 0% --