One of my upcoming challenges will be to determine how to increase the performance of PHP. To prepare I've started writing down some of the ways I've encountered throughout my time working with it. This list covers general cases and goes down toward some very specific instances.
The biggest thing you can do to speed up your overall application performance is ensure you are using an accelerator. Normally PHP has to recompile a script from source code into bytecode instructions every time it is accessed, whether or not the script has changed. These extensions will store the compiled version of scripts and automatically detect when the original file is changed.
In the past files that contained classes would have to be manually required, often listed for inclusion multiple times between files. Sometimes a particular routine wouldn't even need some of those classes, yet they would be included anyway. By autoloading classes that overhead can be avoided. This can also simplify development by not requiring explicit declaration of class usage, which can mitigate some potential errors if a class require is forgotten or assumed included on a previous file and then changed.
Lightweight Object Constructors
More of a design philosophy that helps keep things simple and lightweight, this deals with object creation. The act of creating an object should be lightweight, such that simply creating an object doesn't read thirty files from the file system, try to connect to half a dozen remote sites, or even pull data from the database. This means the user of your object is free to call only the functions they need and not worry about the object doing things it doesn't need for those actions. Data which your methods need can be wrapped into another protected method to check if it is already loaded, load & store if needed, and return the stored data. An object constructor should only handle incoming variables and assign to local variables.
A minor concern most of the time, but something to watch out for. Calling
count()on an array is not an especially lightweight operation, especially the bigger the array. When checking the length of an array multiple times where the size won't be changing the result should be stored in a local variable.
Which brings us to
for()loop performance. The same treatment, storing the results in a variable, should be done for any function calls done in the second or third parameter of a for statement, as otherwise these will be executed on every loop.
The general theme: Don't call a function or method more than you really need to.
This may be surprising, but when doing simple token string find/replace with delimiters it can be much faster to
explode()on the delimiter and then iterate over the results. Every other element in the resultant array is the token name to be replaced with the relevant data, while the other elements should be echoed/returned as-is. By simplifying the find process and delegating it to a built-in function this speeds up overall execution.
When all else fails, the best way to determine where the performance is going:
In more general terms, when a specific call is taking longer than it should or a particular process needs to be sped up then installing XDebug, capturing a trace profile, and running it through KCacheGrind can be very useful in determining what's being called the most and what is taking the longest to run.