[TYPO3-Performance] optimizing for loops

Michiel Roos [netcreators] michiel at netcreators.com
Wed Jul 23 21:44:48 CEST 2008


Hi all,

I was wondering about the 'var='.$var is faster than "var=$var" issue
and came accross some optimization articles. One of them stated the
example below (which I had never thought of). It appears that when using
for loops the sizeof($arr) is evaluated multiple times.

So I grepped the code of the trunk and found a couple of lines like:

t3lib/class.t3lib_cs.php:1940:
    for ($i=0; strlen($str{$i}) && $i<$len; $i++) {

t3lib/class.t3lib_cs.php:1995:
    for ($i=0; strlen($str{$i}); $i++) {

t3lib/class.t3lib_cs.php:2032:
    for ( ; strlen($str{$i}) && $n<$p; $i+=$d) {

t3lib/class.t3lib_tceforms.php:1342:
      for ($c=0;$c<count($selItems);$c++) {

t3lib/class.t3lib_tceforms.php:1382:
    for ($c=0;$c<count($selItems);$c++) {

t3lib/class.t3lib_tcemain.php:2024:
         for ($a=strlen($value); $a>0; $a--) {

typo3/sysext/adodb/adodb/drivers/adodb-mssql.inc.php:538:
   for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) {

. . .

Having that in adodb seems like a bad idea.

So I think there is room for optimization in the core. I don't know what
parts are the current performance bottlenecks. Maybe more speed
improvements can be gained elsewhere. But since this was a new idea to
me, it may help someone else.

:-)


Example 1

Here is one simple example that prints an array:

for ($j=0; $j<sizeof($arr); $j++)
    echo $arr[$j]."<br>";

This can be substantially speeded up by changing the code to:

for ($j=0, $max = sizeof($arr), $s = ''; $j<$max; $j++)
  $s .= $arr[$j]."<br>";

echo $s;

First we need to understand that the expression $j<sizeof($arr) is
evaluated within the loop multiple times. As sizeof($arr) is actually a
constant (invariant), we move the cache the sizeof($arr) in the $max
variable. In technical terms, this is called loop invariant optimization.

The second issue is that in PHP 4, echoing multiple times is slower than
storing everything in a string and echoing it in one call. This is
because echo is an expensive operation that could involve sending TCP/IP
packets to a HTTP client. Of course accumulating the string in $s has
some scalability issues as it will use up more memory, so you can see a
trade-off is involved here.

An alternate way of speeding the above code would be to use output
buffering. This will accumulate the output string internally, and send
the output in one shot at the end of the script. This reduces networking
overhead substantially at the cost of more memory and an increase in
latency. In some of my code consisting entirely of echo statements,
performance improvements of 15% have been observed.

ob_start();
for ($j=0, $max = sizeof($arr), $s = ''; $j<$max; $j++)
   echo $arr[$j]."<br>";

Note that output buffering with ob_start() can be used as a global
optimization for all PHP scripts. In long-running scripts, you will also
want to flush the output buffer periodically so that some feedback is
sent to the HTTP client. This can be done with ob_end_flush(). This
function also turns off output buffering, so you might want to call
ob_start() again immediately after the flush.

In summary, this example has shown us how to optimize loop invariants
and how to use output buffering to speed up our code.

-- 
Netcreators BV :: creation and innovation
www.netcreators.com

Interesse in werken bij Netcreators?
http://www.netcreators.com/bedrijf/vacatures/


More information about the TYPO3-Performance mailing list