blog home

Optimizing PHP

Posted by William in backend on June 10th, 2009

An good article providing many insights on optimizing PHP.

Be careful of using PHP arrays.

PHP arrays is not efficient and uses a lot of memory. So be very careful to use PHP arrays, especially if the array could potentially have a lot of elements. Here’s an example:

<?php
$arr = array();
for ( $i = 0; $i < 10000; $i ++ )
$arr[] = $i;

print “Memory used: ” . number_format(memory_get_usage(true)) . “\n”;
?>

This is an array of only 10,000 elements, but this consumes over 2MB of memory. Imagine from your webserver, you have 10,000 concurrent users invoking a script that’s doing something like this, you can easily crash the machine by running out of memory.

The lesson here is that PHP array is only designed to be used for small amount of data, ideally not more than a few hundred items.

be consistent with php function return type

Posted by William in backend on April 20th, 2009

PHP is a type-less language, which gives you the flexibility of, for example, return anything from a function. This, however, can trigger hard-to-find bugs if you abuse it. A better choice would be consistent with return types, where I mean if the function is supposed to return boolean, only return boolean; if it’s supposed to return a string, always return a string; if it’s supposed to return an array, always return an array.

Here are some examples that shows how it can break your code if you do not pay attention to return types.

Example 1. Disaster: return boolean true and string:

function foo ()

{

if ( some_condition() )

return “ERROR_1″;

else if (some_other_condition() )

return “ERROR_2″;

else

return true;

}

So the author of this function is trying to return some error code (in string, bad idea!), or true if everything is good. But the problem is that any string will be evaluated to be true. So if you have a caller like this:

$rtn = foo();

if ($rtn == true)

// foo is good.

else if ( $rtn == “ERROR_1″ )

// handle ERROR_1

You will have a bug here. The “else” section will never be executed, that’s because if you compare any string to boolean true with “==” operator, it is always true. You could use === to force a type check but your callers may not be aware of that. Some solution to this would be:

  • make the function return true or false only, on throw exceptions instead of returning error code
  • if you so intend to return error code, either through string, or use defined constant (a better idea), never return a boolean. For example, rather than return boolean true, return a constant RTN_OK

in other words, when  you design your function, if you decide what type it should return, always return that type.

Example 2: a function that returns an array.

For example, you have a function that tries to get some data from memcache. If no data from memcache found, get it from database, and cache it in memcache.

function get_customers( $bookid )

{

$mc_key = “bk-cust-$bookid”;

if  ( !$customers = $memcache->get( $mc_key ) )

{

// no records in memcache

$customers = array();

$result = mysql_query(”SELECT * FROM book_customers WHERE bookid=$bookid”);

while ($row = mysql_fetch_array($result))

$customers[] = $row;

$memcache->set( $mc_key, $customers ); //cache it.

}

return $customers;

}

The problem of this function is that if there is nothing found in the database initially, you will end up setting an empty array in the memcache, then when you do memcache->get, you will get it back as a boolean true instead.