Table des matières
- More defensive programming practices to survive Web site traffic peaks by Manuel Lemos on 2007-05-29
- PHP compiler performance comparaison by Manuel Lemos on 2010-02-05
At developpment time
Profile you code before you start optimizing it! Otherwise it would be like travelling around a foreign city with signs written in an unreadable language witout any map or GPS. You’ll probably get somewhere, but you wouldn’t have any idea where you are, where you should go and how far are you from the place you need to be. Profiling would allow you to know which parts of code are worth investing into and which aren’t. You can use Zend Studio/Debugger or Xdebug for that.
- xdebug.profiler_enable_trigger = 1 with XDEBUG_PROFILE set in GET/POST or COOKIE
- ou xdebug.profiler_enable = 1
- Profile memory usage of PHP scripts with xdebug
- xdebug.auto_trace = On
- xdebug.show_mem_delta = On
Analyser les données du profiler de XDebug avec webgrind.
Most PHP installations run in “shared nothing” mode where as soon as the request processing ends, all the data associated with the request is gone. It has some advantages, but also one big disadvantage – you can not preserve results of repeated operations. That is, unless you use caching. You should look into caching all operations which take considerable time and can return the same result for a prolonged period of time or same data set. That may include configurations, database queries, service requests, complex calculations, full pages or page fragments, etc., etc. Caching expensive operations is one of the most powerful performance improvements you can do. There are numerous low-level caching solutions – memcached, APC, Zend Server (you can find a good guide to it on DevZone) and others. On top of it, you may look into Zend Framework’s caching infrastructure – which support the backends described above and more and makes caching much easier.
Optimize your data
Usually the most expensive places of the PHP application are where it accesses external data – namely, database or file system or network. Look hard into optimizing that – reduce number of queries, improve database structure, reduce file system accesses, try to bundle data to make one service call instead of several, etc. For more advanced in-depth look, use tools like strace (Unix) and Process Explorer (Windows) to look into system calls your script produces and think about ways to eliminate some of them. You would not be able to eliminate all of them but each of them is a worthy target.
Avoid extra notices/errors/etc
Even suppressed errors have cost in PHP, so try and write your code so it would not produce notices, strict notices, warnings, etc. You may want to enable logging of all errors to examine that. Never enable displaying errors in production though – it will only lead to a major public embarrassment.
Utiliser preg_* seulement quand on ne peut pas faire autrement.
stripos('http://',$website) est 2 fois plus rapide que preg_match('/http:\/\//i',$website)
ctype_alnum() est 5 fois plus rapide que preg_match('/^\s*$/')
Casting "if($test==(int)$test)" est 5 fois plus rapide que preg_match('/^\d*$/')
At build time
Bundle your Class Files
When using Doctrine or any other large OO library or framework the number of files that need to be included on a regular HTTP request rises significantly. 50-100 includes per request are not uncommon. This has a significant performance impact because it results in a lot of disk operations. While this is generally no issue in a dev environment, it's not suited for production. The recommended way to handle this problem is to bundle the most-used classes of your libraries into a single file for production, stripping out any unnecessary whitespaces, linebreaks and comments. This way you get a significant performance improvement even without a bytecode cache (see next section).
The best way to create such a bundle is probably as part of an automated build process i.e. with Phing.
At run time
Use a Bytecode Cache
If you care about performance and don’t use bytecode cache then you don’t really care about performance. Please get one and start using it. If you want ready-made commercially-supported solution with nice GUI, etc., look at Zend Server, if you’re more into compile-it-yourself command-line then you may want to look at APC, or other alternatives.
A bytecode cache like APC will cache the bytecode that is generated by php prior to executing it. That means that the parsing of a file and the creation of the bytecode happens only once and not on every request. This is especially useful when using large libraries and/or frameworks. Together with file bundling for production this should give you a significant performance improvement. To get the most out of a bytecode cache you should contact the manual pages since most of these caches have a lot of configuration options which you can tweak to optimize the cache to your needs.
Use big realpath cache
Realpath cache (added in PHP 5.1.0) is very useful for the engine when it tries to find the unique full name of the file from just filename or relative path. By default, it’s 16K but if you have a lot of files with long pathes, it’s better to increase the size – it would save the expensive disk accesses.
16k is pretty low for most larger PHP applications (particularly ones that use a framework like the Zend Framework). I'd say at least double the cache size if your application uses lots of includes and see where to go from there. You might also want to increase the TTL as long as your directory structure is pretty consistent.
- realpath_cache_size : Determines the size of the realpath cache to be used by PHP. This value should be increased on systems where PHP opens many files, to reflect the quantity of the file operations performed.
- realpath_cache_ttl : Duration of time (in seconds) for which to cache realpath information for a given file or directory. For systems with rarely changing files, consider increasing the value.