PHP Help and Optimize

wc3garage82

New Member
Messages
43
Reaction score
0
Points
0
I'm currently working on tweaking this script for my forum but unfortunately, it took a long time to handle long texts.
This PHP script will parse each line's words and apply appropriate html codes to that word.

Can someone help me optimize it? And make it faster so it can parse long texts faster. Well the original code was calling arrays for each word making it too long but this one will just call an array once. I just want really to make this php script parse a very long text fast (so shorter texts are faster). If anyone may share their scripts like in this one (checking each line and the words in it, and add the appropriate html code to that word)

here:
PHP:
	/**
	* Parse Jass Code MyCode.
	*/

function mycode_add_FixWord($word,$native,$blocks,$values,$types,$bjfunc) {
	
	if(in_array($word,$native)){
		return "<span style=\"color: purple;\">".$word."</span>";
	}

	if(in_array($word,$blocks)){
		return "<span style=\"font-weight: bold;\">".$word."</span>";
	}

	if(in_array($word,$values)){
		return "<span style=\"color: #3333ff;\">".$word."</span>";
	}

	if(in_array($word,$types)){
		return "<span style=\"color: #4477aa; font-weight: bold;\">".$word."</span>";
	}

	if(in_array($word,$bjfunc)){
		return "<span style=\"color: #dd4444;\">".$word."</span>";
	}
  return $word;
}

function mycode_parse_jass($text) { 
  include('plugins/parser/jass.php');
  $native = explode(" ", $Natives);
  $blocks = explode(" ", $Blocks);
  $values = explode(" ", $Values);
  $types = explode(" ", $Types);
  $bjfunc = explode(" ", $BJ_Func);
  //$text = $message[1];
  $bb=true;
  $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
  $special = "[]()";
  $str = "\"";
  $objid = "'";
  $trans = Array(">" => "&gt;", "<" => "&lt;", "&" => "&amp;", ":" => ":", " " => "&nbsp;");
  if (!$bb)
  {
  	$text = strtr($text, $trans);
  }
  else
  {
  	// Do some backwards working
	$tr = array('(' => '(',
				')' => ')',
				'[' => '[',
				']' => ']',
				'&quot;' => '"');
	$text = strtr($text,$tr);
  }
  $result = "";
  $comment = 0;
  $Lines = explode("\n", $text);
  $anchors = array();
  $n = 0;
  $line_counter = 0;
  // First, find all functions and place an anchor there
  foreach($Lines as $Line) 
  {
  	// Leave anchor here?
	$reg = array();
	$anchors[$n] = '';
  	if (ereg('^ *(constant )? *(function|native)  *([a-zA-Z_][a-zA-Z_0-9]*)  *takes', $Line, $reg))
	{
		$l = max(0, $n-12);
		$anchors[$l] .= '<a name="'.strtolower($reg[3]).'"></a>';
	}
	$n++;
  }
  $n = 0;
  foreach($Lines as $Line) 
  {
    $result .= $anchors[$n];

	$Line = rtrim($Line);
	if ($isString) {
	  $result = $result . "</span>";
	}
    $mac = 0;
    $mac = strpos($Line, "//!");
	if ($mac === false) {
	  $mac = strlen($Line);
	  $macros = 0;
	} else {
	  $macros = 1;
	}
    $stop = strpos($Line, "//");
	if ($stop === false) {
	  $stop = strlen($Line);
	  $comment = 0;
	} else{
	  $comment = 1;
	}
    $i = 0;
	$word = "";
	$isString = 0;
	$stringStarter = "";	
	$slashed = 0;
	// Highlight
	while ($i < $stop) {
	  $c = substr($Line, $i, 1);
	  $i += 1;
	  if ($isString) {
	    $result = $result . $c;
	    if ($c == "\\" || $c == "//") {
		  $slashed = ($slashed)? 0:1;
		} elseif (($c == $stringStarter) && !($slashed)) {
		  $result = $result . "</span>";
		  $isString = 0;
		} else {
		  $slashed = 0;
		}
	  } else {
	    // If normal character
	    if (strpos($chars, $c) !== false) {
          $word = $word . $c;
	    // If bracket
	    } elseif (strpos($special, $c) !== false) {
	      $result = $result . $this->mycode_add_FixWord($word,$native,$blocks,$values,$types,$bjfunc) . $this->mycode_add_FixWord($c,$native,$blocks,$values,$types,$bjfunc);
	    	$word = "";
	    // If string
        } elseif (strpos($str, $c) !== false) { 
	      $result = $result . $this->mycode_add_FixWord($word,$native,$blocks,$values,$types,$bjfunc) . "<span style=\"color: blue\">" . $c;
		  $slashed = 0;
		  $word = "";
		  $isString = 1;
		  $stringStarter = $c;
        } elseif (strpos($objid, $c) !== false) { 
	      $result = $result . $this->mycode_add_FixWord($word,$native,$blocks,$values,$types,$bjfunc) . "<span style=\"color: black;text-decoration:underline\">" . $c;
		  $slashed = 0;
		  $word = "";
		  $isString = 1;
		  $stringStarter = $c;
	    // If other character
	    } else {
	      $result = $result . $this->mycode_add_FixWord($word,$native,$blocks,$values,$types,$bjfunc) . $c;
		  $word = "";
        }
	  } // if ($isString)
	}
	$result = $result . $this->mycode_add_FixWord($word,$native,$blocks,$values,$types,$bjfunc);
	// Add Macros
	if ($macros) {
	  $result = $result . "<span style=\"color: #666;\">".strstr($Line, "//!")."</span>";
$comment = 0;
	}
	// Add comment
	if ($comment) {
	  $result = $result . "<span style=\"color: green;\">".strstr($Line, "//")."</span>";
	}
	// Add linebreak
	$result = $result . "<br />";
	$n++;
	$line_counter = $line_counter + 16;
  }
  $result = substr($result, 0, strlen($result)-6); // Remove last linebreak
  //fixes for mybb parser
  $tr = array('(' => '(',
		')' => ')',
		'[' => '[',
		']' => ']');
  $result = strtr($result, $tr);
	$line_counter = $line_counter + 16;
if($line_counter > 600){
$line_counter = 600;
}
/*$result = <<<EOT
<div style="margin:20px; font-weight: normal; font-decoration: none; font-style: normal; width:640px;">
    <div class="smallfont" style="margin-bottom:2px; text-align:left;">Jass:        </div>
    <pre style="text-align:left; margin:0px;padding: 6px; color:#000; width:640px; height:{$line_counter}px; overflow:auto; background-color:#fff; border:1px solid black;">
    $result
    </pre>
</div>
EOT;*/
  return "<div style=\"margin:20px; font-weight: normal; font-decoration: none; font-style: normal; width:640px;\"><div class=\"smallfont\" style=\"margin-bottom:2px; text-align:left;\">Jass:        </div><pre style=\"text-align:left; margin:0px;padding: 6px; color:#000; width:640px; height:{$line_counter}px; overflow:auto; background-color:#fff; border:1px solid black;\"> {$result} </pre></div>";
}
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
That's... a bit of code to get through for a forum post. What I can tell you off the bat is that in_array is inefficient, as it has to compare every item in the array with the item to look for. Faster is to use items as keys an isset($array[$item]). The sequence of ifs is also a potential choke point. You can deal with this by using a single array with words as keys and style as values or (better still) HTML element class names as values. Inline style is acceptable when set from scripts, but should otherwise be avoided. A web search for when to use inline style will turn up plenty of explanations.

With the above changes, mycode_add_FixWord becomes:
PHP:
function mycode_add_FixWord($word, $classes) {
    if (isset($classes[$word])) {
        return "<span class='{$classes[$word]}'>$word</span>";
    }
    return $word;
}

Joining string fragments all at once (in PHP, this is done with implode) is often faster than repeatedly appending to a string. In C this is because appending naively results in Schlemiel the Painter's algorithm. PHP stores the string length along with the contents, so Schlemiel's algorithms isn't used, but repeated concatenations does involve more memory allocations and deallocations which can be even more time consuming than repeatedly counting string lengths (adding items to an array may involve some allocations as the array is expanded, but not as many and not as much memory will be allocated as frequently). Try replacing all the $result = $result . [...] with $result[] = [...], and put a $result = implode("\n", $result); when $result is filled out. With this approach, there won't be any trailing newlines to remove.

To really improve your script, you'll need to profile it, which you can do from your own server (all development should be done on your own server) with the Xdebug extension installed. If you're not running your own server, XAMPP is a popular stack. Search this forum and the web at large for more.
 
Last edited:

wc3garage82

New Member
Messages
43
Reaction score
0
Points
0
o thanks for that
hmm..
how to setup the $classes[$word]
should it be like

$classes[$word] = $word; ??
or
$classes[$word] = "Natives"; ??

--
well, i might just try that since that code is really slow (when used in long texts) in the free hosting server though...
i didn't get the second one, can you give an example ?
 
Last edited:

vv.bbcc19

Community Advocate
Community Support
Messages
1,524
Reaction score
92
Points
48
$classes[$word] = $word;
This could work.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
$classes[$word] = $word;
This would give every word their own class, which would mean each word would be selected separately in the style sheet. You'd use grouping so you wouldn't have to repeat the rule sets, but it's still a waste.

$classes[$word] = "Natives";
This is what makes most sense, isn't it? Since your original code applied inline style depending on whether each word was in a particular list, each list represented a class of words.

i didn't get the second one, can you give an example ?
The second what? Setting classes to the names of the old lists? You move the style you used to have inline to a style sheet, with each class a selector for the appropriate style.

PHP:
$classes = array(
    'integer' => 'native', 'real' => 'native', 'string' => 'native', ...,
);

Code:
.native { color: purple; }
.block { font-weight: bold; }
.value { color: #3333ff; }
.type {
    color: #4477aa;
    font-weight: bold;
}
.bjfunc { color: #dd4444; }

If you must generate $classes from the $Native &c. variables:
PHP:
function mycode_parse_jass($text) {  
  include('plugins/parser/jass.php'); 
  static $classes;
  if (!$classes) {
      $classes = array_merge(
          array_fill_keys(explode(' ', $Natives), 'native'),
          array_fill_keys(explode(' ', $Blocks), 'block'), 
          ...
      );
  }
However, this will be more of a performance hit, as it will have to construct $classes with every request.
 
Last edited:
Top