Settings for high performance Apache, MySQL and PHP
I just got my new Linode to host a few popular applications made with PHP, MySQL and Apache.
Does anyone have any advice for optimizing for high performance? I've been using xdebug to optimize my code, and I'm looking more for settings like httpd.conf and my.cnf.
Thanks!
14 Replies
1) Install a PHP accelerator, such as APC, XCache, or eAccelerator. You can get twice the performance, almost for free. It's a no-brainer!
2) Pay particular attention to the number of Apache processes you spawn (MaxClients, MaxWorkers, etc.) Don't know which linode plan you're on, but limiting MaxClients to 15 would be a good start. Some distros have insanely high defaults which quickly lead to resource exhaustion.
3) If you're using mpmprefork with modphp, you'd be loading up the whole PHP interpreter even when you serve simple static files (such as images, css, javascript). Consider switching to mpmworker with modfcgid. Even better, offload static files to lighttpd or nginx. This is very important for memory-limited environments such as a linode.
4) If you have custom scripts that generate complicated SQL queries, cache the results so that you don't have to run the same queries every time. You can use files for this purpose, or perhaps something a little more elaborate such as Memcached. If you don't have any custom scripts, see if your "popular application" has a caching module/add-on, such as WP Super Cache for WordPress.
5) Give MySQL a generous amount of key_buffer, but don't give it too much or you'll run out of memory.
Cheers,
I did not know that about it loading the whole of PHP for every static request.
Am I right in saying that using a reverse proxy with Squid for dynamic content is pointless?
Can you run lighthttpd together with apache on the same server?
@jonny5alive:
Am I right in saying that using a reverse proxy with Squid for dynamic content is pointless?
Yes.
@jonny5alive:
Can you run lighthttpd together with apache on the same server?
Yes - many Linoders offload static content to lighttpd or nginx. Using Apache to do everything can chew up a lot of memory.
@hybinet:
3) If you're using mpmprefork with modphp, you'd be loading up the whole PHP interpreter even when you serve simple static files (such as images, css, javascript). Consider switching to mpmworker with modfcgid. Even better, offload static files to lighttpd or nginx. This is very important for memory-limited environments such as a linode. This would only happen when creating a new child, right? So, all the more reason to make sure your apache children is set to something higher like 50.
@BarkerJr:
This would only happen when creating a new child, right? So, all the more reason to make sure your apache children is set to something higher like 50.
In that case, you would be loading up 50 instances of the PHP interpreter when you start the server. Of course a lot of RAM is shared between those children, but still a helluva large waste of precious RAM. Think of it: 12-15MB of RAM dedicated to serving nothing but a 12-15KB css/js file? Besides, with MaxClients=50 on anything smaller than a Linode 1080, you'll probably end up running out of RAM as soon as you get enough visitors to make use of all those Apache chidren.
@hybinet:
In that case, you would be loading up 50 instances of the PHP interpreter when you start the server. Of course a lot of RAM is shared between those children, but still a helluva large waste of precious RAM. Think of it: 12-15MB of RAM dedicated to serving nothing but a 12-15KB css/js file? Besides, with MaxClients=50 on anything smaller than a Linode 1080, you'll probably end up running out of RAM as soon as you get enough visitors to make use of all those Apache chidren.
MaxClients is the maximum number of Apache processes, not the number that is created when apache is started.
I would suggest that most of the memory used by an Apache process is in fact shared. On my systems I can watch Apache spin up 5 additional processes, while overall memory consumption increases by maybe 1 MB (at most).
The amount of memory consumed by an Apache PHP process is determined in large part by what it's doing. If it's processing a 'hello world' script then memory usage is minimal. If it's processing some monster script then memory usage is a heck of a lot more.
The majority of my PHP hits are small but have to wait for an API for a second or two (unavoidable), so I'd like to set my ServerLimit fairly high. However there are some PHP hits that do some graphics work and can use 10MB extra, and if they happen to hit at the same time it will be swapdeath.
Anyone care to discuss if this is a good idea? One day everything will work great.
Or, switch to nginx/lighttpd and use fastcgi.
If I have many visitors using a PHP script that unavoidably waits on an external API, but doesn't use much memory, I could run for example 100 of those without running out of memory. Occassionally, a visitor uses another PHP script that uses say 50MB of graphics memory to create a chart, so I couldn't run 100 of that script.
How would nginx/lighttpd and fastcgi help in this situation?
My concern was more, limiting memory usage by a PHP script should happen in PHP, not the web server. Otherwise PHP is going to try to allocate more RAM and the web server is going to deny it.
I've no idea what happens then, but it can't be good.
Setting up APC correctly has fixed my problems. I set up apc.php on my web server which gave graphs and statistics, and found increasing APC memory from 30MB to 60MB has resulted in processes being executed more quickly and CPU use down from 108% to 12%