« サブディレクトリ内も一覧(その3) | メイン | 強引な「require」 »

リファレンス

値、特に大きな配列など、たくさんのデータを渡すときには、「リファレンス」というものを用いると良いらしい。・・・ということで、どのくらい有効なのか?と思ってやってみた。

一応書いておきますが、サンプルで実行できるのは、下の方に書いてある「リファレンスの使用法」みたいなものです。ベンチマークとは関係ありませんので、適当に実行してください。

まず、基準となる配列「$cnt個」に乱数「rand」を格納した。それを「my」変数に書き込むサブルーチンを作って「$count」回「Benchmark」してみました。(基本的な書式)

「$count,$cnt」の値と、その結果
「$count」の値「$cnt」の値リファレンス不使用リファレンス使用
Type110001007.142.48
Type21000101.871.26
Type310000112.9711.58
Type410010005.771.32

この計測が正しい方法なら、配列が大きければ大きいほど、「リファレンス」を使ったほうが処理が速いようだ。

ちなみに、「print」に関係する部分を削除すると、より明らかに差が出た。

ただ、「リファレンス」を参照する(本には「デリファレンス」と書いてあった)には、配列なら「@」を、ハッシュなら「%」を「リファレンス変数」の前につける必要がある。実は、これが結構面倒だったりする。

また、個別に参照するには通常と同じように「$」を頭につける。つまり「$$array[0]」や「$$hash{num}」のように・・・。で、何故か知らないけど、配列の場合だけは「@$array[0]」でも参照できる。普通の配列でも「@a[0]」で参照できる(この辺はおそらくPerl5のみ)。このおかげで「@」が「"(ダブルクォート)」の中では展開されるようになり、文字として表示するには「エスケープ」しないといけなくなったんだろう。

この他に「矢印記法」というものもあり、例えば「$$array[0](または@$array[0])」の場合は「$array->[0]」と記述する事もできる。ハッシュなら「$$hash{num}」が「$hash->{num}」といった具合。ややこしいけど、なかなか面白いことを考える。

この「リファレンス」というやつは、サブルーチンに対しても作る事ができるし、さらに、その「リファレンスされたサブルーチン」が、それぞれ違う値を返したり・・・と、なかなか奥が深い。理解するのは結構時間がかかりそうだ。

ソースコード

#!/usr/bin/perl
 
#BEGIN{
#	print "Content-type: text/plain\n\n";
#	open(STDERR, ">&STDOUT");
#	$|=1;
#}
 
%h = (
	'num1'	=> 1,
	'num2'	=> 2,
);
 
@a = (1,2);
 
$hash = \%h;
$array = \@a;
 
print <<EOM;
Content-type: text/plain
 
\$h{num1} = $h{num1}
 
\$\$hash{num1} = $$hash{num1}
\%\$hash{num1} = %$hash{num1}
\$hash->{num1} = $hash->{num1}
 
\$a[0] = $a[0]
\@a[0] = @a[0]
 
\$\$array[0] = $$array[0]
@\$array[0]  = @$array[0]
\$array->[0] = $array->[0]
 
EOM

ベンチマーク用ソースコード

#!/usr/bin/perl
 
BEGIN{
	print "Content-type: text/plain\n\n";
	open(STDERR, ">&STDOUT");
	$|=1;
}
 
use Benchmark;
 
$count	= 1000;
$cnt	= 100;
$dat1	= "reftest1.txt";
$dat2	= "reftest2.txt";
 
srand;
for(0 .. $cnt){
	@nums[$_] = rand;
}
 
open(OUT, "> $dat1");
close(OUT);
open(OUT, "> $dat2");
close(OUT);
 
sleep 1;
 
@t = timethese($count, {
	'Refuse'	=>	'&use_ref;',
	'RefNouse'	=>	'&nouse_ref;',
});
 
exit(0);
 
sub use_ref{
	my $r_nums;
	$r_nums = \@nums;
	open(OUT, ">> $dat1");
	foreach(@$r_nums){
		print OUT "$_\n";
	}
	close(OUT);
}
 
sub nouse_ref{
	my @n_nums;
	@n_nums = @nums;
	open(OUT, ">> $dat2");
	foreach(@n_nums){
		print OUT "$_\n";
	}
	close(OUT);
}

カテゴリ:

トラックバック

このエントリーのトラックバックURL:

同一カテゴリの最新記事

最近のエントリー

Amazon.co.jp

Creative Commons License
このブログは、次のライセンスで保護されています。 クリエイティブ・コモンズ・ライセンス.
Powered by
Movable Type 3.36
Amazon.co.jp