Vikash
Vikash

Reputation: 989

Most efficient way to parse custom templates in PHP

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

Answers (1)

Jeffrey
Jeffrey

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

Related Questions