I recently (loosely) translated a file-based perl cgi bulletin board
script to php.
Both scripts now produce the same output. But the
perl version is substantially faster than my php
version. Perhaps someone else can figure out how to
optimize the sorting of file-based 'threads' of posts,
which is where the bottleneck seems to be.
Can someone else do a better job?
Both these scripts use a readdir to get the contents of
the current directory. Every post is a file with
a numerical name like 0004
0004.0001 would be a reply to post 0004
0004.0002.0001 would be the first reply to the second reply to 0004
So you want to assemble individual subject threads as
sorted, numerically ascending arrays of string.
But the collection of all such arrays of strings (threads) want to be
sorted in reverse order, so newer threads appear (on the top of the page)
before older threads. So you want to sort those based on the
first string in each array of string (the root post of that thread).
the perl:
#generic sort function by Joseph Hall, jo****@5sigma.com
sub fieldsort {
my ($sep, $cols);
if (ref $_[0]) {
$sep = '\\s+'
}
else {
$sep = shift;
}
unless (ref($cols = shift) eq 'ARRAY') {
die "fieldsort columns must be in anon array";
}
my (@sortcode, @col);
my $col = 1;
for (@$cols) {
my ($a, $b) = /^-/ ? qw(b a) : qw(a b);
my $op = /n$/ ? '<=>' : 'cmp';
push @col, (/(\d+)/)[0] - 1;
push @sortcode, "\$${a}->[$col] $op \$${b}->[$col]";
$col++;
}
my $sortfunc = eval "sub { " . join (" or ", @sortcode) . " } ";
my $splitfunc = eval 'sub { (split /$sep/o, $_)[@col] } ';
return
map $_->[0],
sort { $sortfunc->() }
map [$_, $splitfunc->($_)],
@_;
}
==slower, uglier php that does produce the same output ============
function how_deep($msg)
{
$cnt=0;
$notdone=$msg;
while($notdone)
{
$notdone = strstr($msg,".");
$msg=substr($notdone,1);
$cnt++;
}
return($cnt);
}
function threadBase($msg)
{
$substr = ereg_replace(strstr($msg,"."),"",$msg);
return($substr);
}
function threadsort($files)
{
$fcnt = count($files);
sort($files, SORT_NUMERIC);
$list=array();
for($i=0; $i<$fcnt; $i++)
{
$key = $files[$i];
$depth = $this->how_deep($key);
if($depth == 1)
{
$thread_head = array();
$thread_head[] = $key;
$list[$key] = $thread_head;
$this->threadkeys[] = $key;
}
else
{
$thread_key = $this->threadBase($key);
$list[$thread_key][] = $key;
}
}
rsort($this->threadkeys, SORT_NUMERIC);
return($list);
}