By: Sheepy
Date: 2013-12-03
Time: 05:15
|
f_Loc_PrmRead optimization
Hi. I am tracking the performance of my current project, and realise that f_Loc_PrmRead is spending the most time of all TBS functions.
(Of all functions in my current project, actually.)
So I tried to optimise it, mainly by refactoring condition checks. The main loop is still recognizable.
In dynamic columns example and display columns example, I get 5-10% speed up to whole program.
static function f_Loc_PrmRead(&$Txt,$Pos,$XmlTag,$DelimChrs,$BegStr,$EndStr,&$Loc,&$PosEnd,$WithPos=false) {
$BegLen = strlen($BegStr);
$BegChr = $BegStr[0];
$BegIs1 = ($BegLen===1);
$DelimIdx = false;
$DelimCnt = 0;
$DelimChr = '';
$BegCnt = 0;
$SubName = $Loc->SubOk;
$Status = 0; // 0: name not started, 1: name started, 2: name ended, 3: equal found, 4: value started
$PosName = 0;
$PosNend = 0;
$PosVal = 0;
// Variables for checking the loop
$PosEnd = strpos($Txt,$EndStr,$Pos);
if ($PosEnd===false) return;
while (true) {
$Chr = $Txt[$Pos];
if ($DelimIdx) { // Reading in the string
$b4PosEnd = $PosEnd - 1; // Skip to next delimiter or end of position
while ( $Chr !== $DelimChr && $Pos < $b4PosEnd ) {
$Pos++;
$Chr = $Txt[$Pos];
}
if ($Chr===$DelimChr) { // Quote found
if ($Chr===$Txt[$Pos+1]) { // Double Quote => the string continue with un-double the quote
$Pos++;
} else { // Simple Quote => end of string
$DelimIdx = false;
}
}
} elseif ($BegCnt===0) { // Reading outside the string
// Analyzing parameters
if (($Chr===' ') || ($Chr==="\r") || ($Chr==="\n")) {
if ($Status===1) {
if ($SubName && ($XmlTag===false)) {
// Accept spaces in TBS subname.
} else {
$Status = 2;
$PosNend = $Pos;
}
} elseif ($XmlTag && ($Status===4)) {
self::f_Loc_PrmCompute($Txt,$Loc,$SubName,$Status,$XmlTag,$DelimChr,$DelimCnt,$PosName,$PosNend,$PosVal,$Pos,$WithPos);
$Status = 0;
}
} elseif (($Chr===';') && ($XmlTag===false)) {
self::f_Loc_PrmCompute($Txt,$Loc,$SubName,$Status,$XmlTag,$DelimChr,$DelimCnt,$PosName,$PosNend,$PosVal,$Pos,$WithPos);
$Status = 0;
} elseif (($Chr==='=') && ($Status===2||$Status===1)) {
if ($Status===1) {
$PosNend = $Pos;
}
$Status = 3;
} else {
switch ($Status) {
case 1:
case 4:
break;
case 2:
case 3:
if ($XmlTag && $Status === 2) {
self::f_Loc_PrmCompute($Txt,$Loc,$SubName,$Status,$XmlTag,$DelimChr,$DelimCnt,$PosName,$PosNend,$PosVal,$Pos,$WithPos);
$Status = 1;
$PosName = $Pos;
} else {
$Status = 4;
$DelimCnt = 0;
$PosVal = $Pos;
}
break;
default:
$Status = 1;
$PosName = $Pos;
}
$DelimIdx = strpos($DelimChrs,$Chr);
if ($DelimIdx===false) {
if ($Chr===$BegChr && ($BegIs1 || substr($Txt,$Pos,$BegLen)===$BegStr)) {
$BegCnt++;
}
} else {
$DelimChr = $Chr;
$DelimCnt++;
$DelimIdx = true;
}
}
} else {
if ($Chr===$BegChr && ($BegIs1 || substr($Txt,$Pos,$BegLen)===$BegStr)) {
$BegCnt++;
}
}
// Next char
$Pos++;
// We check if it's the end
if ($Pos===$PosEnd) {
if ($XmlTag) {
if ($Txt[$Pos-1]==='/') $Pos--; // In case last attribute is stuck to "/>"
self::f_Loc_PrmCompute($Txt,$Loc,$SubName,$Status,$XmlTag,$DelimChr,$DelimCnt,$PosName,$PosNend,$PosVal,$Pos,$WithPos);
break;
} elseif ($DelimIdx===false) {
if ($BegCnt>0) {
$BegCnt--;
} else {
self::f_Loc_PrmCompute($Txt,$Loc,$SubName,$Status,$XmlTag,$DelimChr,$DelimCnt,$PosName,$PosNend,$PosVal,$Pos,$WithPos);
break;
}
}
$PosEnd = strpos($Txt,$EndStr,$PosEnd+1);
if ($PosEnd===false) return;
}
}
$PosEnd = $PosEnd + (strlen($EndStr)-1);
} |
Speed up not as much as I hoped, but still.
Should be possible to gain more speed with a rewrite, but would also be more risk and time...
|