Make Your PHP Faster
I was reading about some php performance tips at work today and decided to throw together some of the ways to make your php site faster.
Here’s a couple of short tips to avoid making your site lag for the user:
- Unset your variables. This frees up a surprising amount of memory
- Use memcache
- Turn on apache’s mod_deflate
- If your database is local then close your connections when you’re done with them
- If your database is remote then use persistant connections
- Don’t use functions inside of a for loop control expression unless absolutely necessary. Example :
for($i=0;$i<some_big_calculation(20);$i++)
The some_big_calculation function will be called every iteration. -
Use string concatenation instead of embedding variables in strings.
$some_string = "asdf $asdf2 asdf"; //bad $some_string = 'asdf '.$asdf2.' asdf'; //good
-
When including files, use at least a relative path so PHP doesn’t have to look in the entire path.
include("./some_file.php"); // looks in the current directory include("wrong.php"); // searches every directory in the path
- Try not to use include_once or require_once. They are more expensive and it really isn’t that hard to only include files once
- Not everything needs to be an object. There is a fair amount of overhead when doing everything OOP.
- Use output buffering to make everything seem faster.
Hopefully I didn’t miss any of the big ones.
June 27th, 2009 at
1. It’s a double edge sword from the testing I have found out. Yes it does free ram, but dear load it does it really impact processing time. You’ve got to know how to use it correctly.
6. Is a good one. I did notice that you are doing a post increment, instead of pre increment. It’s one less op code, which would be a micro optimization in your example.
7&8 I’ve seen go both ways.
9. So do functions, but I really don’t want to work on that code..
10. Another one I’ve seen go both ways. Switch is cleaner looking, but would say not as flexible with advanced stuff.
11. Output buffering does speed things up since the processor doesn’t have to go back and forth on figuring out when to flush stuff out to the browser. Also you can compress things to help the speed of the transport of data to the browser.
I have a tip that in my bench marking has yielded ~12%:
Use do{…}while(); instead of while.
example:
while($row = mysql_fetch_assoc($qry))
{
…
}
could be done like this:
$cnt = mysql_num_rows($qry);
if($cnt > 0)
{
do
{
$row = mysql_fetch_assoc($qry);
…
–$cnt;
}while($cnt < 0);
}
Sorry if this comment sounds mean, didn't mean to make it sound that way at all.
June 27th, 2009 at
Example 7 has a syntax error.
June 27th, 2009 at
Thanks for pointing that out. It looked like a single quote in the wordpress editor. I really need to stop using that thing.
June 27th, 2009 at
Write clean, consistent and efficient APIs. Remember that the bottleneck in your website is (many times) more likely to be connected to database access than the speed at which your scripting language runs. A well written site minimises data access and database overhead, and runs faster than a poorly optimised site implemented in a faster-executing scripting language.
June 27th, 2009 at
I really hate it when people respond to lists like this with condescending remarks for each point the author makes, so I will try my best not to be an asshole and be constructive :-)
1. Very true. mysql_free_result() can also be useful for larger queries.
2. This is not really PHP specific, but when used correctly [like caching method / function calls or really anything, it can make a very significant difference]
3. This really is specific to Apache. It can also be used to deflate non text/html requests as well, like Javascript, CSS, etc.. which is one reason I love this module so much :-) [http://httpd.apache.org/docs/2.0/mod/mod_deflate.html]
4. Whether it’s local or not doesn’t make much of a difference here… closing the resource when you’re done with it does make sense, though. But you could find yourself chasing your tail finding a bug in your code if you forgot that you closed the connection.
5. I can’t say that I find this to be even remotely true. Persistent connections are great when you have steady traffic to a server, but once your site goes up on digg your connections will dry up fairly quickly and your visitors will be sad. This also goes for high keep-alive settings [for apache]. The remote / local factor really doesn’t make any difference [IMO].
6. This is true… though I’ve found that most people will throw a count() in there, which usually makes an unnoticeable difference in page load time. But if it is another function which does take a while, then you could run into response time issues.
7. Again, this usually makes an unnoticeable difference in page load time. Even then, passing more than one argument to the echo construct is technically faster than concatenation [is some tests I’ve seen].
8. True, a full path to the file can also be beneficial: /var/www/html/somesite.com/_inc/something.inc
9. I agree… I have a function which I call to return include paths for me, so I might call: import(“file.inc”); which will return the full path to the file if I haven’t called import() with “file.inc” as an argument yet. Otherwise it will return false, telling me that I have already asked for the include path, and therefore already required the file.
10. I agree 100%. Abstracting things into objects can make testing, caching and applying the DRY principle much easier, though. It also makes it much easier for more than one person to work on the files.
11. _Seem_ faster? I don’t think I can recall a time where using this makes a difference [at least the theory of catching your output buffer and purging it all at once]. The server still needs to do everything to create the HTML to send back to the user. Though I have had luck with flush()ing output to a user at certain parts of the script, plus they get their headers sooner.
Thanks for the article :-)
June 27th, 2009 at
“If your database is local then close your connections when you’re done with them”
I thought that it wasn’t necessary to call mysql_close(), that PHP automatically calls it for you at the end of your script. Granted, it may be good form to call it, but if it’s being called automatically, how is not calling it affecting PHP performance?
June 27th, 2009 at
Not as bad as average “oooh, double quotes will kill you” tips, but I wouldn’t care much about unsetting variables.
IMHO:
1. Use Opcode cache
2. Cache PHP output
3. If you need to care about much else, you probably shouldn’t be using PHP.
June 27th, 2009 at
Great Post!
Just a little mention about number 8 in the list.
8. The include command is not a function and therefore it should not be wrapped in (). It’s also a good thing to use single quotes when handling strings so PHP doesn’t need to look for variables in the string.
Here’s how i had done it
include ‘./some_file.php’;
Any comments or suggestions?
June 27th, 2009 at
It’s always good to pass variables by reference, whenever you want to read them but not modify then. This way you can save lots of memory and processing time by not having to copy the whole thing twice whenever you pass it around.
Example:
function do_some_work($data) {
// this is bad, because $data is a
// copy of the original variable
}
function do_some_work(&$data) {
// this is better, because there is no
// copy involved internally, the original
// variable is passed through
}
// $mydata is a big, big array with lots of stuff
do_some_work($mydata);
June 27th, 2009 at
@Daniel Great comment! I didn’t even know that was possible in PHP. I will definitely use that in the future. I’ll probably even update the post. Thanks.
June 28th, 2009 at
Yeah, and the ultimate performance tip: stop programming in PHP and use C or Assembler with CGI bridge.
Come on, are really important several milliseconds in the execution of a script if you can save seconds caching the database? Real optimization is not like this Google guy says.
Optimizing PHP: cache and more cache. And don’t use a template system like Smarty, PHP is a template language itself.
What do you prefer, save less than 1 millisecond in the execution of your script or save weeks by writing a maintainable code, using frameworks, etc?
June 28th, 2009 at
Daniel is wrong – using a reference almost NEVER uses less memory. PHP is copy-on-write, so unless you tried to modify $data inside the function, making the reference will actually INCREASE your memory usage.
October 16th, 2009 at
TML, you are right :)