Reputation: 989
Let's say we are writing a custom templating system and we would like a link to be displayed where template contains {{link:http://example.com/something}}click here{{link}}
.
What will be the most optimal way to parse this?
Some approaches I can think of: Simple string manipulation using substr
. Using preg_replace
with back substitution etc.
Upvotes: 0
Views: 195
Reputation: 1804
For my own parser, i'm using a mixture of "strpos / substr" and preg_replace. Why? well, its all in the numbers.
If your string to parse, contains alsmost only a {{link}} tag, without Start- & Endnoice, preg_replace is quicker e.g.
STARTNOICE{{link:http://example.com/something}}click here{{link}}ENDNOICE
But, the more characters are in Endnoice, the slower preg_replace is, compared to substr / strpos :) Just 100 characters in Endnoice, will make substr / strpos being quicker than preg_match!
The best way to proof this, is with code ofcause. So here is a testscript. It compares the sum of time for substr with preg_match
Even though substr requires way more code, it is more efficient :)
Greetz, JB
p.s. some results:
Startnoice = Endnoice = 100, /w 100 loops
$substrTime:
0.004448 Seconds
$pregTime:
0.004752 Seconds
.
Startnoice = Endnoice = 1000, /w 100 loops
$substrTime:
0.005598 Seconds
$pregTime:
0.023844 Seconds << waaaay slower
.
Startnoice = Endnoice = 10000, /w 100 loops
$substrTime:
0.009028 Seconds
$pregTime:
0.278836 Seconds << Dont use preg_replace
.
<?PHP
$startNoice = 1;
$endNoice = 100;
for( $jb = 0; $jb < 100; $jb++ )
{
$string = randomgenerator( $startNoice ) . '{{link:http://example.com/something}}click here{{link}}.' . randomgenerator( $endNoice );
/**************/
// Strpos / substr
/**************/
/* Start the timer */
$Start = '{{link:';
$StartEnd = '}}';
$Stop = '{{link}}';
$StartLen = strlen( $Start );
$StartEndLen = strlen( $StartEnd );
$StopLen = strlen( $Stop );
$time_start = microtime_float();
$strpos['Start'] = strpos( $string, $Start );
$start = substr( $string, 0, $strpos['Start']);
$end = substr( $string, $strpos['Start'] );
$strpos['StartEnd'] = strpos( $end, $StartEnd, $StartLen );
$strpos['Stop'] = strpos( $end, $Stop, $StartLen );
$url = substr( $end, $strpos['Start'] + $StartLen, ($strpos['StartEnd'] - $strpos['Start'] - $StartLen) );
$text = substr( $end, $strpos['StartEnd'] + $StartEndLen, ($strpos['Stop'] - $strpos['StartEnd'] - $StartEndLen) );
// Replace the link
$NewString1 = $start . '<a href="' . $url . '">' . $text . '</a>' . substr( $end, $strpos['Stop'] + $StopLen );
/* Stop the tumer */
$time_end = microtime_float();
$substrTime[] = $time_end - $time_start;
/**************/
// Preg_match
/**************/
$time_start = microtime_float();
$NewString2 = preg_replace('/{{link:(.*)}}(.*){{link}}/', '<a href="$1">$2</a>', $string);
$time_end = microtime_float();
$pregTime[] = $time_end - $time_start;
}
echo '$substrTime: . <br />';
echo round( array_sum( $substrTime ), 6) . ' Seconds';
echo '<br />';
echo '$pregTime: . <br />';
echo round( array_sum( $pregTime ), 6) . ' Seconds';
function randomgenerator( $length )
{
$string = 'abcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()_+=-{}][|\::",./';
$r = '';
for( $i = 0; $i < $length; $i ++ )
{
$r .= $string[ rand(0, strlen( $string ) -1 ) ];
}
return $r;
}
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
?>
Upvotes: 3