Doctoral Inspirations
While reading my Gmail yesterday, I saw a sponsored link titled “The PHP Doctor“. Being a self-proclaimed PHP expert myself, I was interested to see exactly how good this PHP Doctor is. He has a blog–a PHP tips and tricks blog. The first post was about functions, and their use in writing modular code. Although the post used a solid example of functions, I couldn’t help but notice a few sloppy performance issues. The following are tips that I have created after reading that post, and the second post on the page.
- Where possible, do not use functions in the entrance condition for loops. Consider the following example: (From The PHP Doctor*)
for( $x = 0 ; $x < strlen( $InString ); $x++ ) {
if (strstr( $OKChars , $InString[$x] ) ) $OutString .= $InString[$x];
}
Note that for every iteration of that loop, the valuestrlen( $InString )remains the same. However, on each iteration of the loop, the function is run. To avoid running this function each iteration, the value should be assigned to a variable before the first iteration:
for ( $x = 0,$c = strlen( $InString ); $x < $c; $x++) {
if ( strstr( $OKChars , $InString[$x] ) ) $OutString .= $InString[$x];
}
++$i,$i++,$i += 1, and$i = $i + 1all have the same basic effect, but they are indeed different. Using using $i++ or ++$i is faster than using$i += 1 or $i = $i + 1. For those who don’t remember, $i++ and ++$i are respectively, the post increment and the pre increment operators. The difference between the two is that pre increment increments $i, then returns the incremented value, whereas post increment returns the value of $i, then increments $i.- Although PHP doesn’t really care, try to avoid implicitly casting numerical types to strings when it is not necessary. Consider a function that takes a numer, $Number, and rounds it to the nearest hundredth. (Note: this can be done via PHP’s round function:
round($Number,2)). Here is an example from The PHP Doctor*:
function roundToTwo( $Number ) {
//pow(10, -3) = .001
$Number += pow( 10 , -3 ); //Make sure the thousandths place is populated
$Number = round( $Number * pow( 10 , 2 ) ) / pow( 10 , 2 );
//Make sure the thousandths place is populated
$Number += pow( 10 , -3 ); //pow() returns float or int (false on error)
//Take the decimal point, and the following two characters.
$Number = substr( $Number , 0 , strpos( $Number , '.' ) + 3 );
return $Number;
}
Rounding is a mathematical function, but the preceding function relies on properties of strings. One downside of this is performance; another is formatting:roundToTwo()will return a string, and because strings have no concept of significant digits, non-significant digits will be returned. (return value could be something like 123.00) Anyway, with a little more thought, we can find a way to do this without using strings. When round is passed only one argument, it will round the argument to the nearest integer. It follows thatround($Number*100)/100will function the same asroundToTow($Number). But suppose we want to avoid usinground()… Recall that if we are rounding to n decimal places, we round up when the digit in the (n+1)th decimal place is greater than or equal to 5, and down otherwise. Adding 5 to this digit will accomplish this. Thus, we can now use thefloor()function instead ofround():floor($Number*100 + .5)/100. - In the previous example, not the use of pow(x,y) where x and y are constant. For better performance, calculate the value pow(x,y), and use that value in your program. In some cases, this will also lead to more readable code.