Monday, November 9, 2009

Simple Optimizing Tips for PHP - Part I

As we write PHP code (or any language for that matter) we begin to start thinking about optimizing code. But even though our intentions are for "the greater good", we sometimes miss things that should be obvious. This article is one of many to come that hopes to point these things out to you, and in the process train your mind to think of quicker steps you may otherwise haven't really thought about.

Today's article takes a look at:

Loop Arrays
When we use loops, the goal is simple: iterate through an array set, and do something with the results. Most developers understand this quite well but they build the basic looping structure without considering how poor methods of iteration will affect their code's performance.

Example:

$sql = "SELECT * FROM `user`";
$rst = $dbh->fetch_rows($sql);

for($i = 0; $i < count($rst); $i++) {
// do something
}


For some, the problem is quite clear. For others, the code above seems quite valid and perfectly fine. However, the above can cause serious latency in your application(s) if you follow this type of constructing loops enough times.

The issue exists with the loop piece $i < count($rst);

Consider that the query we used returns 2000 records. While the for loop is completely valid, the issue exists in that, for each iteration, you are now counting the number of results ($rst) in each and every iteration!. This means that if we have 2000 records, it's going to get a count of our $rst array 2000 times!

What's worse is that when you issue the count() function on a big array, it must load this array into memory, check it, and then finally clear the tmp data. This in turn puts a small hamper on the server when done once, but when we are doing it 2000 consecutive times just for the sake of iteration, the overhead becomes very evident.

The solution for this is quite simple. You should first just get a count of the number of records, assign it to a value before the loop, and then use this for your iteration. For the PHP engine, is much faster to check a flat numeric value 2000 times rather than issue the count() sequence (explained above) 2000 times.


The Full Solution

$sql = "SELECT * from `user`";
$rst = $dbh->fetch_rows($sql);

$total_users = count($rst);
for($i = 0; $i < $total_users; $i++) {
// do something
}


Where the above will find some flack from experienced users is the situation where you may really need a count of an array. Such situations include: removing a key from an array, adding a new key to an array, popping values off an array, etc...

For these situations, the solution is not to use a for loop, but rather a foreach loop. Since a foreach loop iterates one array key at a time, we can remove/add array keys without the need to keep a count. Plus, if you really want to keep track of your $i variables count you can just assign $i before foreach loop and increment it within the foreach.

Example:

$sql = "SELECT * FROM `user`";
$rst = $dbh->fetch_rows($sql);

$i = 0;
foreach($rst as $key => $value) {
echo "|| $key => $value => $i || ";
$i++;
}


While the above can be optimized a hundred different ways, the point is that we should be taking into consideration how a script in PHP operates. Instead of just forcing it to carry out redundant operations and continue to put more overhead/waste of processor cycles on our server, why not try to optimize the code and make a cleaner, faster application?

Tune in next week for my next article: Recursive Functions.

No comments:

Post a Comment