Hehe ok lets start with the idea:
Let's take a look into YaBB.pl. What we have in there is the most important part of the board. Why? Because
ALL stuff in there will be called every time the forum gets a hit. No matter if someone is viewing boardindex, messageindex, a thread or does anything else like marking something as read.
Now what are the slowest perl code parts in general? There are two things which come into mind:
- loops
- file access
Now where do we have that in YaBB.pl?
Well a lot of stuff access files. But there is a place where we have really a lot of it:
&LoadCookie; # Load the user's cookie (or set to guest)
&LoadUserSettings; # Load user settings
&banning; # Check for banned people
&WriteLog; # Write to the log
&LoadIMs; # Load IM's
if($currentboard ne "") { &LoadBoard; } # Load board information
Now there is a lot of essential stuff in there, but not really all:
&WriteLog;
hm Writelog is pretty essential, eh? Lets take a look at the sub, it's located in Subs.pl:
sub WriteLog {
my($curentry, $name);
my $field = $username;
if($field eq "Guest") { $field = "$user_ip"; }
fopen(LOG, "$vardir/log.txt");
my @online = <LOG>;
fclose(LOG);
fopen(LOG, ">$vardir/log.txt", 1);
print LOG "$field|$date\n";
foreach $curentry (@online) {
$curentry =~ s/\n//g;
($name, $date1) = split(/\|/, $curentry);
$date2 = $date;
chomp $date1;
chomp $date2;
&calctime;
if($name ne $field && $result <= 15 && $result >= 0) { print LOG "$curentry\n"; }
}
fclose(LOG);
fopen(LOG, "+<$vardir/clicklog.txt",1);
my @entries = <LOG>;
seek LOG, 0, 0;
truncate LOG, 0;
print LOG ";
foreach $curentry (@entries) {
$curentry =~ s/\n//g;
chomp $curentry;
($name, $date1, $dummy) = split(/\|/, $curentry);
$date2 = $date;
chomp $date1;
chomp $date2;
&calctime;
if($result <= $ClickLogTime && $result >= 0) { print LOG "$curentry\n"; }
}
fclose(LOG);
}
What do we have there:
...
fopen(LOG, "$vardir/log.txt");
...
fopen(LOG, ">$vardir/log.txt", 1);
...
fopen(LOG, "+<$vardir/clicklog.txt",1);
So we have 3 file access in here. Those 3 files get accessed all the time. That's crappy, eh?
So what can be done? We have multiple options.
We can remove who is online and clicklog completely. That will definitively boost up most. But who would forego "who is online"? So what other option do we have? We can limit the call of this function:
if ($action eq "") { &WriteLog; }
This code will cause YaBB only to log people if they access either the boardindex or the message index. This won't affect the who is online log too much but will reduce the file access a lot. Now to even increase the stpeed, we remove the clicklog part completely. This is however a relinquishment but I think that this is ok because it will speed up most.
So a mod for all this changes would look like this:
<edit file>
YaBB.pl
</edit file>
<searchfor>
&WriteLog; # Write to the log
</searchfor>
<replace>
if ($action eq "") { &WriteLog; }
</replace>
<edit file>
Sources/Subs.pl
</edit file>
<searchfor>
sub WriteLog {
my($curentry, $name);
my $field = $username;
if($field eq "Guest") { $field = "$user_ip"; }
fopen(LOG, "$vardir/log.txt");
my @online = <LOG>;
fclose(LOG);
fopen(LOG, ">$vardir/log.txt", 1);
print LOG "$field|$date\n";
foreach $curentry (@online) {
$curentry =~ s/\n//g;
($name, $date1) = split(/\|/, $curentry);
$date2 = $date;
chomp $date1;
chomp $date2;
&calctime;
if($name ne $field && $result <= 15 && $result >= 0) { print LOG "$curentry\n"; }
}
fclose(LOG);
fopen(LOG, "+<$vardir/clicklog.txt",1);
my @entries = <LOG>;
seek LOG, 0, 0;
truncate LOG, 0;
print LOG ";
foreach $curentry (@entries) {
$curentry =~ s/\n//g;
chomp $curentry;
($name, $date1, $dummy) = split(/\|/, $curentry);
$date2 = $date;
chomp $date1;
chomp $date2;
&calctime;
if($result <= $ClickLogTime && $result >= 0) { print LOG "$curentry\n"; }
}
fclose(LOG);
}
</searchfor>
<replace>
sub WriteLog {
my($curentry, $name);
my $field = $username;
if($field eq "Guest") { $field = "$user_ip"; }
fopen(LOG, "$vardir/log.txt");
my @online = <LOG>;
fclose(LOG);
fopen(LOG, ">$vardir/log.txt", 1);
print LOG "$field|$date\n";
foreach $curentry (@online) {
$curentry =~ s/\n//g;
($name, $date1) = split(/\|/, $curentry);
$date2 = $date;
chomp $date1;
chomp $date2;
&calctime;
if($name ne $field && $result <= 15 && $result >= 0) { print LOG "$curentry\n"; }
}
fclose(LOG);
}
</replace>