Basic LAMP Performance Tuning

Linux:
(2.6 kernel only)
Check vm.swappiness: sysctl -A|grep swap
The default is 60, which is generally too high... if it is still the default, set it to 20:

sysctl -w vm.swappiness=20
echo "vm.swappiness = 20" >> /etc/sysctl.conf

Verify adequate RAM and processor resources with sar. If IOWait is high, check iostat ('iostat 2 10' will do 10 polls at 2 second intervals).

(P4/Xeon only)
Check for hyperthreading issues (proc usage will be abnormally high... check /var/log/sa/sar*. If total proc usage disagrees with individual proc usage then HT needs to be disabled in the BIOS.

Apache:

Increase MaxClients as needed (We are going to enable KeepAlives, so we're probably going to need to bump this up, depending on utilization, as KeepAlives cause connections to take at least KeepAliveTimeout seconds to close)
set 'KeepAlive Off' to 'KeepAlive On'
set MaxKeepAliveRequests to 500 (default... some PHP apps such as XCart will need this to be much higher... try 2000)
Set KeepAliveTimeout to 5

For very high traffic sites, you'll want to increase MinSpareServers and possibly MaxSpareServers as well.

Another thing to note is that the AllowOverride setting will significantly reduce performance. In short, Apache needs to search every directory in which AllowOverride is permitted for a .htaccess file with every operation. Needless to say, this is less than optimal. Ideally, .htaccess should be disabled and incorporated into the vhost configuration. See http://httpd.apache.org/docs/2.0/howto/htaccess.html for more information.

MySQL:

Download and run http://www.day32.com/MySQL/tuning-primer.sh and follow its suggestions (especially enable log-slow-queries and set long-query-time to a lower value... I generally use 3 or 4).

Optimize all tables with:

for i in `mysql -B -e "show databases"|grep -v Database`; \
do for j in `mysql $i -B -e "show tables;"|grep -v Tables_`; \
do mysql $i -e "optimize table $j";done;done;

or for Plesk (untested)
MYSQL_AUTH="-uadmin -p`cat /etc/psa/.psa.shadow`"; for i in `mysql
$MYSQL_AUTH -B -e "show databases"|grep -v Database`; do for j in `mysql
$MYSQL_AUTH $i -B -e "show tables;"|grep -v Tables_`;do mysql $MYSQL_AUTH $i
-e "optimize table $j";done;done;

You can also add the authentication info to /root/.my.cnf e.g.
[Client]
username=admin
password=pleskpassword

PHP:

PHP runs terribly without some kind of PHP accelerator installed.
Install APC or EAccelerator (note that APC is not compatible with Zend Optimizer)
I generally use APC, as it is much easier to install, works well without customization, and has a better history of being bug-free. There are also nice graphs to track performance.
EAccelerator has a smaller memory footprint (~5M/process), and offers slightly better performance, but is more of a pain to install and update (source compile). The project is also not as actively developed as APC.

APC:

pear upgrade pear
pear channel-update pear.php.net
pear channel-update pecl.php.net
mount -o remount,exec /tmp
pear install pecl/apc
mount -o remount,noexec /tmp
echo "extension=apc.so" >/etc/php.d/apc.ini
echo "apc.shm_size=128" >>/etc/php.d/apc.ini
service httpd graceful

Note: Since XML-RPC has recently been disabled on PEAR, Red Hat RHEL 4 may need:

 
mount -o remount,exec /tmp
pear upgrade --force http://pear.php.net/get/PEAR-1.3.3
pear upgrade --force http://pear.php.net/get/PEAR-1.4.3.tar
pear upgrade PEAR
pear channel-update pear.php.net
pear channel-update pecl.php.net
pear install pecl/apc
mount -o remount,noexec /tmp
echo "extension=apc.so" >/etc/php.d/apc.ini
echo "apc.shm_size=128" >>/etc/php.d/apc.ini
 

Do not use "pecl install apc" as it will not parse php.ini and you may have an issue with reaching the memory limit while trying to install.

Verification: Check out the statistics by copying /usr/share/pear/apc.php into a document root. Do not place this in a permanently accessible public location, it gives out too many details about what is going on in the background.

You likely need to allocate more RAM in apc.shm_size if you note errors such as the following in your error logs at some point:

[apc-warning] GC cache entry "script.php" was on gc-list for 5096725 seconds

From what I can tell, garbage collection does not work too well if over 85% of APCs RAM is in use by scripts.

EAccelerator:

Ensure that it is compiled with --enable-shared and that eaccelerator.shm_only = 1 is in the config file.

To illustrate what a difference this makes, here are 3 runs of ab -n 50 -c 3 against transcendlinux.com's front page (not the best real-world test, but fine for illustration)

--
No acceleration:
Requests per second: 12.03 [#/sec] (mean)
Time per request: 249.478 [ms] (mean)

Requests per second: 12.36 [#/sec] (mean)
Time per request: 242.647 [ms] (mean)

Requests per second: 12.36 [#/sec] (mean)
Time per request: 242.705 [ms] (mean)

--
APC:
Requests per second: 66.13 [#/sec] (mean)
Time per request: 45.369 [ms] (mean)

Requests per second: 67.57 [#/sec] (mean)
Time per request: 44.400 [ms] (mean)

Requests per second: 65.74 [#/sec] (mean)
Time per request: 45.632 [ms] (mean)

--
EA:
Requests per second: 73.88 [#/sec] (mean)
Time per request: 40.604 [ms] (mean)

Requests per second: 64.68 [#/sec] (mean)
Time per request: 46.384 [ms] (mean)

Requests per second: 73.74 [#/sec] (mean)
Time per request: 40.681 [ms] (mean)

Submitted by jkelly on Thu, 2007-07-05 19:14. categories [ | | | | ] login or register to post comments