PHP Code Optimization

On this page you can find some PHP code optimizations. This list of tipps & tricks  is not complete at all and i will try to add more tipps and tests. I did the tests on windows and linux environments to make safe that the results are rough valid. It’s really important for a good PHP developer that he or she is aware of some performance aspects of the code. The following tipps are a best practice example of coding smart PHP code. This article is a part of the web-application performance series.

Echo vs. print and concatenation

The comparison of the two output options is the oldest of the PHP-scene. It’s wrong to assert that echo ist faster than print because of the procedural overhead that the print instruction produces. These two instructions are both builtin-constructions of the PHP-language and not, as often assumed, print is a function and echo a language-construct. The only difference versus echo and print is, that echo has no return value but print returns always 1 (see: manual). The next Problem is the often unknown difference between outputing a couple of substrings with echo and concatenate substrings to a longer string. The first operation runs with the commata operator and the second one with the point operator. It’s the normal case to use echo with the point-operator, but it’s not best practice.

$str1 = “Test1“;
$str2 = “Test2“;

echo “Hello world, this is “ . $str1 . “  & “ . $str2 . "!";

If you have long sub strings, then your concatenation will take a very long time. Below you can see the best practice example:

$str1 = “Test1“;

$str2 = “Test2“;

echo “Hello world, this is “ , $str1 , “  & “ , $str2,"!";

Quotes

The myth of optimizing quotes is often not welcome in the PHP-community, but the benchmark-tests shows us, that single quotes are a bit faster than double quotes. The reason is, that the parser is looking for variables which could possibly be in there. And this process takes more time, than the simple text parsing. You should use double quotes only in the case, that you want to put variables in the string.

Search strings

We compared strstr() and strpos() with each other. The task is to find a substring in a string. Below you can see the two scenarios:

$sub = '@';

$str = 'mailme@example.com';

//the first way

if(strstr($str, $sub) !== FALSE) echo 'found';

else echo 'not found';

//the second way

if(strpos($str, $sub) !== FALSE) echo 'found';

else echo 'not found';

After testing these two ways in a loop, i noticed that strpos() works faster and uses less memory than strstr().

Comparison of the starting characters

To compare the first n token of two strings, you have 2 options. You can use strncmp() with is the smarter one or you can use substr(). The result should be clear. With just one PHP function call the script performs faster. The best practice scenario is strncmp():

$str1 = 'Teststring1;

$str2 = 'Test_string1';

$len = 4; //compare the first 4 tokens

if(strncmp($str1, $str2, $len) === 0) return true;

else return false;

if(substr($str1,0,$len) == substr($str2,0,$len)) return true;

else return false;

The result of the test shows that strncmp() is faster than the substr() alternative. The advantage of using strncmp() inceases with the length of the string. Another scenario could be, to use strpos(…) like strncmp() to compare the starting characters. I did this test and the result points out that strncmp() was faster than strpos() (but not significant).

Counting operations (count(), sizeof() und strlen())

If you want to know the number of elements in an array to work with it, you can use the sizeof() (or count()) method to get it. It’s often used, but not best practice , to implement these methods in the condition area of loops. It would be better to get the number of elements before the loop starts. Otherwise you count the elements in every single iteration. Note, that count() is faster than sizeof(). The reason is, that sizeof() is just a synonym of count().

//wrong way

for($i = 0; $i < count($arr); $i++){

//magic

}

//right way

$size = count($arr);

for($i = 0; $i < $size; $i++){ //magic }

Read loops and modify loops

Often, you have to modify data in complex structures , such an array. Here you can use the foreach()-construction of PHP. Beware, that the performance of this code depends on the operation that you want to perform. After testing a set of operations (reading, modifying, unset) i noticed, that read-operations perform better with foreach(). The modification of an array works better with the for-loop. The reason is, that PHP does more hash-lookups, if you use it with foreach() and $key => $value. Note, that this loop performs faster if you get $value by reference.

//best practice for reading

foreach($arr as  &$value){

//magic with $value

}

To modify an array you should use something like this.

//best practice for modification

$keys = array_keys($arr);

$c = count($keys);

for($i = 0; $i < $c; $i++){

//magic with $arr[$keys[$i]]

}

Testing array index

To find out whether a array index exists or not you can use the in_array() function or the isset() function.  The in_array() function expects two parameters. The first parameter is the $needle (the index to find) and the second one is $haystack (array). PHP searches into $haystack for $needle. The isset() function ( just expects the variable) simply searches in the symbol table whether this index is set or not.

in_array('test', $array);
isset($array['test']);

I found out that isset() is faster than in_array(). Do not think, that this improvement isn’t significant. The speed improvement increases proportionally with the size of the array.

File handling

You have more than one option to perform file handling in PHP. A simple read from a file can be performed by file() and file_get_contents(). Be aware that the first one returns just an array with all rows. You have to implode this array with a glue (e.g. a whitespace) to use it as a string. The second function returns exactly this string. In most cases you need the content as a string. Use file_get_contents() to do this work. It is more than 200% faster (depends on length). If you need the rows to do your task, then it would be faster to use the file() function.

Replacing strings

If you want to replace strings in PHP you can use str_replace() and preg_replace(). For simple patterns you should use str_replace(). This function is much faster than preg_replace() because it works stupid and simple. But beware,that preg_replace() is much faster, if you have a complex pattern. One call to preg_replace() is smarter than 2 or more calls to str_replace().

Constants & configuration

Defining global constants is a mighty method for large web applications to bring some flexibility into it. To realize this, PHP implements a method called define(). Since PHP supports OOP you can define constants in classes. This method is not only better structured but also faster than the define() alternative. It’s more comfortable to build a configuration class, that contains all constants.

//old way

define('DB_HOST', 'localhost');

define('DB_USER', 'mysql');

define('DB_PW', '**************');

define('DB_DB', 'application');

//other way

class DB{

const HOST = 'localhost';

const USER = 'mysql';

const PW = '**************';

const DB = 'application';

}

Statistical probability (LazyEnd)

Sometimes you have to do some decisions about the program flow of your application. Here you would have a significant increase on performance if you let the parser perform the small functions, before it performs the expensive functions.

if(expensive_function() || small_function()){

//magic

}

//is significant slower than

if(small_function() || expensive_function()){

//magic

}

But why? The parser performs from the left to the right. When the function on the left returns true, then the complete condition becomes true. The parser don’t execute the second function, because it is not necessary. This works for logical AND too. Put the small function or the fastest expression on the left site. In the case of the logical AND becomes the complete condition wrong, if one expression is wrong.

Another statistical optimization aspect is to consider well about the structure of if-else and switch instructions. You should keep the conditions, that are most likely, on top of you if/else or switch construct, to avoid work and save time.

If vs. switch vs. ternary operations

The general opinion about If vs. Switch is, that the If/else construct have a better implementation and therefore it performs faster. I tried to get light into the dark with browsing the code and the internals of PHP. It’s right, that the If/else implementation looks smarter and so i can confirm the general opinion. But there is a construct that works faster than If/else and it’s called ternary operations. Below i listed an example of the simple usage of a tenary operation (a smarter handling of If/else):

return ($condition)? $if_value : $else_value;

Increment operations

To increment an integer variable (e.g. during a loop iteration) you have a few options. For that, PHP provides the pre- and post-increment operator. Here we put the light on the performance of this operators. The fastest method is to use the pre-increment ++$i, because the first step is the increment and after that PHP returns the new value. This is done in approx. 1 cycle. The second-fastest is the post-increment $i++. Here, PHP uses another procedure to handle this. And the third-fastest is the normal assignment, because PHP can add, divide, etc. and with a variable or a number. That makes this operation trickier and even slower for the execution.

Pass by Reference

The PHP interpreter passes arguments by reference (by default), when the value will not be modified. But, when the value will be modified in (for example) a function, then PHP is going to clone this value (simple value or object). When you want to modify a given argument and after that, you want to return this value, use the following way:

//wrong way:

function x($argument){
//do magic with the array
return $argument;
}

//right way:
function x(&$argument){
//do magic with the array
} 

2 thoughts on “PHP Code Optimization

Leave a Reply

Your email address will not be published. Required fields are marked *