blosxomの記事ファイルを検索するサブルーチンを書き換えてみる試み。
オリジナルの &$entries サブルーチンは、インデントが深くなっていたり、制御構造の and を多用していたりで読みにくかったので、同じ処理をしつつもう少し見やすいように書き換えてみました。
多分同じ処理になっていると思うのですが、保証はできません。
blosxomプラグインの、entriesサブルーチンの形式で書いてます。
sub entries {
return sub {
package blosxom;
my (%files, %indexes, %others);
find(
sub {
# $depthより深ければ復帰
my $curr_depth = $File::Find::dir =~ tr[/][];
return if ($depth && $curr_depth > $depth);
# 現在の時刻、ファイル名、更新時刻の設定
my $time = time;
my $name = $File::Find::name;
my $mtime = stat($name)->mtime;
# ディレクトリなら復帰
return if (-d $name);
# 読めないなら復帰
return unless (-r $name);
# ファイル名のマッチ
my ($path, $fn) =
$name =~ m{^$datadir/(?:(.*)/)?(.+)\.$file_extension$};
$path ||='';
# パターンにマッチしていないか、indexか、
# .で始まるファイル名なら、%otherに追加して復帰
if (!$fn || $fn eq 'index' || $fn =~ /^\./) {
$others{$name} = $mtime;
return;
}
# 未来の記事だったら復帰 (許可していない場合)
return if (!$show_future_entries && $mtime > $time);
# %filesに追加
$files{$name} = $mtime;
# 静的表示の処理 (%indexesに追加)
my $check_index = "$static_dir/$path/index.$static_flavours[0]";
return unless (
param('-all')
|| !-f $check_index
|| stat($check_index)->mtime < $mtime
);
$indexes{$path} = 1;
my $d = join('/', (nice_date($mtime))[5,2,3]);
$indexes{$d} = $d;
$static_entries and $indexes{($path ? "$path/" : '') . "$fn.$file_extension"} = 1;
}, $datadir
);
return (\%files, \%indexes, \%others);
};
}
ベンチマークを取るために以下のようなスクリプトを作成。entries0 がオリジナルの、entries1が今回書き換えたサブルーチンです。
package blosxom;
use strict;
use CGI qw/:standard :netscape/;
use File::Find;
use File::stat;
use Time::localtime;
use Benchmark;
our $datadir = "/var/apache/htdocs/blosxom2/entries";
our $depth = 0;
our $show_future_entries = 0;
our $file_extension = "txt";
our $static_entries = 0;
our $static_dir = "/var/apache/htdocs/blosxom2/statics";
our @static_flavours = qw/html rss/;
our %month2num = (nil=>'00', Jan=>'01', Feb=>'02', Mar=>'03', Apr=>'04', May=>'05', Jun=>'06', Jul=>'07', Aug=>'08', Sep=>'09', Oct=>'10', Nov=>'11', Dec=>'12');
timethese(200, {
'test0' => '&entries0;',
'test1' => '&entries1;',
});
sub entries0 {
package blosxom;
my(%files, %indexes, %others);
find(
sub {
my $d;
my $curr_depth = $File::Find::dir =~ tr[/][];
return if $depth and $curr_depth > $depth;
if (
# a match
$File::Find::name =~ m!^$datadir/(?:(.*)/)?(.+)\.$file_extension$!
# not an index, .file, and is readable
and $2 ne 'index' and $2 !~ /^\./ and (-r $File::Find::name)
) {
# to show or not to show future entries
(
$show_future_entries
or stat($File::Find::name)->mtime < time
)
# add the file and its associated mtime to the list of files
and $files{$File::Find::name} = stat($File::Find::name)->mtime
# static rendering bits
and (
param('-all')
or !-f "$static_dir/$1/index." . $static_flavours[0]
or stat("$static_dir/$1/index." . $static_flavours[0])->mtime < stat($File::Find::name)->mtime
)
and $indexes{$1} = 1
and $d = join('/', (nice_date($files{$File::Find::name}))[5,2,3])
and $indexes{$d} = $d
and $static_entries and $indexes{ ($1 ? "$1/" : '') . "$2.$file_extension" } = 1
} else {
!-d $File::Find::name and -r $File::Find::name and $others{$File::Find::name} = stat($File::Find::name)->mtime
}
}, $datadir
);
return (\%files, \%indexes, \%others);
}
sub entries1 {
package blosxom;
my (%files, %indexes, %others);
find(
sub {
# $depthより深ければ復帰
my $curr_depth = $File::Find::dir =~ tr[/][];
return if ($depth && $curr_depth > $depth);
# 現在の時刻、ファイル名、更新時刻の設定
my $time = time;
my $name = $File::Find::name;
my $mtime = stat($name)->mtime;
# ディレクトリなら復帰
return if (-d $name);
# 読めないなら復帰
return unless (-r $name);
# ファイル名のマッチ
my ($path, $fn) =
$name =~ m{^$datadir/(?:(.*)/)?(.+)\.$file_extension$};
$path ||='';
# パターンにマッチしていないか、indexか、
# .で始まるファイル名なら、%otherに追加して復帰
if (!$fn || $fn eq 'index' || $fn =~ /^\./) {
$others{$name} = $mtime;
return;
}
# 未来の記事だったら復帰 (許可していない場合)
return if (!$show_future_entries && $mtime > $time);
# %filesに追加
$files{$name} = $mtime;
# 静的表示の処理 (%indexesに追加)
my $check_index = "$static_dir/$path/index.$static_flavours[0]";
return unless (
param('-all')
|| !-f $check_index
|| stat($check_index)->mtime < $mtime
);
$indexes{$path} = 1;
my $d = join('/', (nice_date($mtime))[5,2,3]);
$indexes{$d} = $d;
$static_entries and $indexes{($path ? "$path/" : '') . "$fn.$file_extension"} = 1;
}, $datadir
);
return (\%files, \%indexes, \%others);
}
sub nice_date {
my($unixtime) = @_;
my $c_time = ctime($unixtime);
my($dw,$mo,$da,$ti,$yr) = ( $c_time =~ /(\w{3}) +(\w{3}) +(\d{1,2}) +(\d{2}:\d{2}):\d{2} +(\d{4})$/ );
$da = sprintf("%02d", $da);
my $mo_num = $month2num{$mo};
return ($dw,$mo,$mo_num,$da,$ti,$yr);
}
記事ファイルが101個ある状態で試してみたところ、思ったより速度は改善されているようです。
$ perl test.pl
Benchmark: timing 200 iterations of test0, test1...
test0: 15 wallclock secs (13.11 usr + 1.88 sys = 14.99 CPU) @ 13.34/s (n=200)
test1: 10 wallclock secs ( 8.20 usr + 1.87 sys = 10.07 CPU) @ 19.86/s (n=200)
$ perl test.pl -all=1
Benchmark: timing 200 iterations of test0, test1...
test0: 11 wallclock secs (10.01 usr + 1.21 sys = 11.22 CPU) @ 17.83/s (n=200)
test1: 9 wallclock secs ( 8.02 usr + 1.09 sys = 9.11 CPU) @ 21.95/s (n=200)
YukiWiki 2.1.2
(C) 2000-2004 by Hiroshi Yuki.