50+ best practices to optimize PHP code performance

Like any scripting language, PHP can be used in a variety of applications. The down-side for most programmers is that when they learn how to write PHP, they do not always learn how to write PHP with speed and optimization in mind. This article addresses most common ways you can improve your code with minor changes that will yield large gains as well as teach you how to become a better PHP developer.

One of the most important things you can do when improving PHP application performance is begin measuring your application to find a baseline performance time for different parts of your application. If you do not know which parts of your application are slow or have bottlenecks, you will not know where to begin optimizing your code for better performance. There are many commercial and free applications that can be used to measure PHP performance. See the article PHP Profilers Compared for further information.

 

  • If a method can be static, declare it static. Speed improvement is by a factor of 4.
  • echo is faster than print, use echo’s multiple parameters instead of string concatenation.
  • Set the max value for your for-loops before and not as a function in the loop:
    $len = count($big_array); for ($i=0; $i<$len; $i++) {...}
  • Unset your variables to free memory, especially large arrays.
  • Avoid magic methods like __get(), __set() and __autoload()
  • To find out the time when the script started executing, $_SERVER['REQUEST_TIME'] is preferred to time()
  • See if you can use strncasecmp, strpbrk and stripos instead of regex
  • strtr is faster than str_replace by a factor of 4
  • It’s better to use select statements (switch() { case ”: }) than multi if and else if statements.
  • Error suppression with @ is very slow.
  • Turn on apache’s mod_deflate
  • mod_gzip which is available as an Apache module, compresses your data on the fly
    and can reduce the data to transfer up to 80%
  • Close your database connections when you’re done with them
    (although PHP does it for you upon full page load or end of script execution)
  • Use single quotes in indexes: $row['id'] is 7 times faster than $row[id]
  • Use sprintf instead of variables contained in double quotes, it’s about 10x faster.
  • Incrementing a local variable in a method is the fastest. Nearly the same as calling a local variable in a function.
  • Incrementing a global variable is 2 times slower than a local var.
  • Incrementing an object property (eg. $this->prop++) is 3 times slower than a local variable.
  • Incrementing an undefined local variable is 9-10 times slower than a pre-initialized one.
  • Just declaring a global variable without using it in a function also slows things down (by the same amount as incrementing a local var). PHP does a pricy check to see if the global exists.
  • Methods in derived classes run faster than ones defined in the base class.
  • A function call with one parameter and an empty function body takes about the same time as doing 7-8 $localvar++ operations. A similar method call is of course about 15 $localvar++ operations.
  • Surrounding your string by instead of will make things interpret a little faster since php looks for variables inside “…” but not inside ‘…’.
  • When working with strings and you need to check that the string is of a certain length, you’d understandably would want to use the strlen() function. This function is pretty quick since it’s operation does not perform any calculation but merely returns the already known length of a string available in the zval structure (internal C struct used to store variables in PHP). However because strlen() is a function it is still somewhat slow because the function call requires several operations such as lowercase & hashtable lookup followed by the execution of said function. In some instance you can improve the speed of your code by using an isset() trick.
    if (!isset($foo{5})) { echo 'Foo is too short'; } ?>
    instead of
    if (strlen($foo) < 5) { echo 'Foo is too short'; } ?>
    Calling isset() happens to be faster then strlen() because unlike strlen(), isset() is a language construct and not a function meaning that it’s execution does not require function lookups and lowercase. You’ll have no overhead on top of the actual code that determines the string’s length.
  • When incrementing or decrementing the value of the variable $i++ happens to be a much slower then ++$i. It is because instead of 4 opcodes used for $i++ you only need 3. Post incrementation actually causes the creation of a temporary var that is then incremented while pre-incrementation increases the original value directly. This is one of the optimization that opcode optimizer such as Zend’s PHP optimizer utilizes.
  • Use array_pad(). A common case when assigning multiple variables from an array is to use the list() construct with the explode() function to split the string and set the parts of the list to each variable like so: list($foo1, $foo2, $foo3) = explode('/', 'var1/var2/var3'); However, the problem is then created where you may not be bringing in as many variables for each part of the list. If you are missing a variable or two when you explode, you will get a nice notice from PHP. The usual response to this is to use the error suppression operator to dismiss the error (@list()). In this case, $foo3 will be set to NULL and your script will suffer a speed penalty for use of the @ operator. To alleviate this problem it is better to use array_pad to only fill the array with the number of variables that you have instead of causing and suppressing an error at the cost of your performance.
    list($foo1, $foo2, $foo3) = array_pad(explode('/', 'var1/var2'), 4, NULL);
  • Not everything has to be OOP, often it is too much overhead, each method and object call consumes a lot of memory.
  • Do not implement every data structure as a class — arrays are useful too
  • If you have very time consuming functions in your code, consider writing them as C extensions
  • Profile your code. A profiler shows you, which parts of your code consumes how many time. The Xdebug debugger already contains a profiler. Profiling shows you the bottlenecks in overview
  • Excellent article about optimizing your PHP code by John Lim
  • Do use foreach for looping collections/arrays. PHP4 items are byval, < PHP5 items are byref
  • Do consider using the Singleton Pattern as you will have only one instance of an object.
  • Do use POST over GET for all values that will wind up in the database for TCP/IP packet performance reasons.
  • Do use ctype_alnum, ctype_alpha and ctype_digit over regular expression to test form value types for performance reasons.
  • Do use full file paths in production environment over basename/file_exists/open_basedir to avoid performance hits for the filesystem having to hunt through the file path. Once determined, serialize and/or cache path values in a $_SETTINGS array. $_SETTINGS['cwd'] = cwd(./);
  • Do use require/include over require_once/include_once to ensure proper opcode caching.
  • Do use tmpfile or tempnam for creating temp files/filenames
  • Do use a proxy to access web services (XML or JSOM) on foreign domains using XMLHTTP to avoid cross-domain errors. eg. foo.com<–>XMLHTTP<–>bar.com
  • Do use error_reporting(E_ALL); during debug.
  • Do set Apache allowoverride to “none” to improve Apache performance in accessing files/directories.
  • Do use a fast fileserver for serving static content (thttpd) static.mydomain.com, dynamic.mydomain.com
  • Do serialize application settings like paths into an associative array and cache or serialize that array after first execution.
  • Do use PHP output control buffering for page caching of heavily accessed pages
  • Do use PDO (or a major PHP framework such as CakePHP, Symfony, CodeIgniter, Yii or phpiphany) for prepared statements over native DB prepare. mysql_attr_direct_query=>1
  • Do NOT use SQL wildcard selects. eg. SELECT * (although selecting all columns manually yields same retrieval time as issuing SELECT *; therefore try to select only the columns you are actually going to use)
  • Do use database logic (queries, joins, views, procedures) over loopy PHP.
  • Use caching whenever possible. This article defines basic caching techniques. To sum it up, use arrays for caching big chunk of data in the memory directly. Use APC or eAccelerator on a single server. Use memcache on multiple servers when you scale you application.
  • APC being the fastest caching method does not scale well. Redis and Memcache can be used for cross-process/multi-server communications. Data in Redis storage will remain even after a server reboot. Don’t want to install Redis (it’s just a 1 line in console)? Use Memcache. If you can’t install any third-party packages, you can use Shared Memory – but your PHP should be compiled with support of shmop-functions. If we take APC as our unit of measure in the following benchmark, we can draw the following conclusion:
    • APC – best performance – speed 1
    • Redis – speed 1.6
    • Shared memory – speed 130
    • Memcache – speed 192 (slowest)

    Head over to the Redis VS Memcache comparison to see the stats in action.

  • Here is another interesting resource that provides comparison of most of the items listed above
  • Lastly, follow Yahoo performance rules for best practices on optimizing loading times of your website

Source


4 Comments

  1. An extra 1 stings the detritus, or at minimal another blog post bites the dust. Your weblog rocks my article network hold up the terrific causes .

Leave a Reply

*