« トロイの木馬URL投稿が多かったので大ざっぱに対応 | Home | しつけも道徳も自分で考えるものであって科学に求めるモノでない »

2006年12月20日

不必要なメモリ使用時の速度への影響

csvファイルからデータ検索するロジックで、
以下の2つのロジックにどれくらいの速度差がでるか試してみました。

・ロジック1(funcBigRead)
 csvの1行から全項目を取り出して検索キーとキー項目がヒットしたら出力
・ロジック2(funcSmallRead)
 csvの1行からキー項目だけ取り出して検索キーとキー項目がヒットしたら全項目を取り出して出力

・csvデータは日本郵政公社から全国一括郵便番号csv(121,684件)を拝借
・出力する検索キーは最終行の"9071801"

実行結果


s/iter funcBigRead funcSmallRead
funcBigRead 2.40 -- -53%
funcSmallRead 1.13 113% --

とうぜんロジック2の方がメモリ使用量も少なく速いだろうと予想していましたが、
ロジック2の方がロジック1に比べて2倍速い結果がでました。

データが多く、且つ最終行がヒットするという極端なシチュエーションとはいえ、
普段からロジック2を当然のように使えるようにしたいなぁ。
そしてお約束のように普段書いていたスクリプトはロジック1。

実行スクリプト


use strict;
use warnings;
use Benchmark qw(timethese cmpthese);

my $result = timethese(5,{
'funcBigRead' => 'funcBigRead',
'funcSmallRead' => 'funcSmallRead',
});
cmpthese($result);

sub funcBigRead{
my $keyZipCode = '"9071801"';
open(FILE,"< ./KEN_ALL.CSV") || die 'file open error.';
while (){
my ($id,$oldZipCode,$newZipCode,$prefectureNameKana,$townNameKana,$subNameKana,
$prefectureName,$townName,$subName) = split(/,/);
if ($keyZipCode eq $newZipCode) {
print "$prefectureName$townName\n";
last;
}
}
close(FILE);
}

sub funcSmallRead{
my $keyZipCode = '"9071801"';
open(FILE,"< ./KEN_ALL.CSV") || die 'file open error.';
while (){
my (undef,undef,$newZipCode) = split(/,/);
if ($keyZipCode eq $newZipCode) {
my ($id,$oldZipCode,$newZipCode,$prefectureNameKana,$townNameKana,$subNameKana,
$prefectureName,$townName,$subName) = split(/,/);
print "$prefectureName$townName\n";
last;
}
}
close(FILE);
}

#
#実行結果
#
#Benchmark: timing 5 iterations of funcBigRead, funcSmallRead...
#"沖縄県""八重山郡与那国町"
#"沖縄県""八重山郡与那国町"
#"沖縄県""八重山郡与那国町"
#"沖縄県""八重山郡与那国町"
#"沖縄県""八重山郡与那国町"
#funcBigRead: 12 wallclock secs (11.87 usr + 0.13 sys = 12.00 CPU) @ 0.42/s (n=5)
#"沖縄県""八重山郡与那国町"
#"沖縄県""八重山郡与那国町"
#"沖縄県""八重山郡与那国町"
#"沖縄県""八重山郡与那国町"
#"沖縄県""八重山郡与那国町"
#funcSmallRead: 6 wallclock secs ( 5.49 usr + 0.15 sys = 5.64 CPU) @ 0.89/s (n=5)
# s/iter funcBigRead funcSmallRead
#funcBigRead 2.40 -- -53%
#funcSmallRead 1.13 113% --
#

コメントする