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.