Contents

Linux Tuning

Hard Drive Tuning

  • RAID Arrays

Proper tuning of RAID Arrays is far more difficult and extensive a process than will be discussed here, however some basic tips will be given. hdparm -tT /dev/sda1 may be used to determine the buffer and disk speeds of hard drive arrays. A typical result might look like this (4x250GB PATA on 3Ware 7506-4LP):

/dev/sda5:
Timing buffer-cache reads: 1000 MB in 2.00 seconds = 500.00 MB/sec
Timing buffered disk reads: 300 MB in 3.00 seconds = 100.00 MB/sec

Linux 2.4.x: There are three parameters which can immediately affect these results. They are vm.min-readahead, vm.min-readahead and vm.pagecache. You can set these parameters temporarily like echo "2048" >/proc/sys/vm/min-readahead. These parameters may be set permanently by adding lines like vm.max-readahead=2048 to /etc/sysctl.conf. After testing various possibilities, the above RAID array was determined to work best at:
vm.max-readahead=512
vm.max-readahead=12288
vm.pagecache=10 40 100

Linux 2.6.x: Use blockdev like this: blockdev --setra 6144 /dev/sda Test different values to determine the fastest value for your server.

Here are the optimized results:

/dev/sda5:
Timing buffer-cache reads: 1068 MB in 2.00 seconds = 534.00 MB/sec
Timing buffered disk reads: 404 MB in 3.01 seconds = 134.22 MB/sec
  • IDE Drives

If you have a modern UDMA5 hard drive interface, a command like hdparm -X69 -d1 -u1 -m16 -c3 /dev/hda may help you optimize your settings. To make this permanent, add the command to /etc/rc.local.

Apache Tuning

  • Conf Settings

EnableMMap On should be used on most machines provided files are not served from a network drive like NFS and the machine is not a multi-processor server. Some higher number processor servers (especially Solaris) may have problems with this setting.

EnableSendFile On should be used on most machines provided files are not served from a network drive like NFS and the machine is not a multi-processor server. Some higher number processor servers (especially Solaris) may have problems with this setting.

AllowOverride None provides the best performance so it should be used unless the ability to override settings is required in .htaccess files.

DirectoryIndex should be as short a list as possible with no wildcards. More popular index page names should be placed first to limit searching.

Options FollowSymLinks simplifies the process of following symlinks by not requiring a stat on every subdirectory as is required by SymLinksIfOwnerMatch.

ExtendedStatus off prevents 2 calls to timing functions for each request (with many requests per web page, this is a significant savings).

HostnameLookups off will prevent Apache from having to run a reverse DNS lookup on every client IP address. If these are absolutely necessary, limit their use to the specific files or directories that need them. Reverse lookups can be performed by your log analysis software if they are necessary for statistical reporting.

MaxClients 256 should be set for busy websites. To service more than this, Apache must be recompiled.

SendBufferSize should be large enough that most pages can be sent to the client in one chunk rather than waiting for the client to acknowledge receiving data and then continuing to send. This can take several seconds. SendBufferSize is only effective up to the Kernel TCP/IP buffer size which can be set by echoing a number (such as 131072) to /proc/sys/net/core/wmem_max before starting Apache.

Remove all unnecessary modules and directives in the httpd.conf configuration file. This will place the minimum load on the server.

  • Misc Improvements

For an additional 5%-30% improved PHP performance, compile PHP in statically instead of loading it as a module. This will cause some additional pain each time PHP is upgraded (as Apache must be recompiled) but will help squeeze every last drop of server power from your machine. To do this, use --activate-module=src/modules/php4/libphp4.a as an option when running configure on the Apache source.

Consider using a separate web server such as thttpd or TUX for static files such as HTML, archives and images.

If absolute performance is top priority and you're willing to do some work, patches from the Accelerating Apache Project can be applied to make Apache 1.3 or 2.0 from 30%-900% faster.

MySQL Tuning

  • Conf Settings

Enable MySQL Query Cache (4.0+ only). Use the following settings in your my.cnf file:

set-variable = query_cache_type=1
set-variable = query_cache_size=12M (memory size to use for cache)
set-variable = query_cache_limit=1M (size of largest query result to cache)

Enable slow query logging:

set-variable = log_slow_queries=/var/log/mysqlslow (locate of slow query log)
set-variable = long_query_time=2 (minimum time in seconds of a long query)

PHP Tuning

  • Conf Settings

session.save_handler=mm Configure sessions to be saved in memory instead of files (caution: 4.3.0+ only). This saves at least 1-2 touches to disk for each PHP page which uses sessions.

register_gobals off to save unnecessary variable initialization.

output_handler = ob_gzhandler will compress your HTML before sending it to the client. This makes the transfer time shorter and frees Apache up to handle other requests sooner. Only use this if you have the processor power available.

Place an ini file at /usr/local/lib/php-cli.ini to prevent the CLI from having to search for the ini file each time it is called.

  • Misc Improvements

Compile PHP with the following settings: --enable-inline-optimization, --with-mm, and --disable-debug.

Use an accelerator extension which caches the opcode of PHP pages such as:
ionCube PHP Accelerator
Turck MMCache
zend Optimizer
afterBurner
APC

Consider using an output cache such as:
Turck MMCache
zend Optimizer
jpcache v2

  • Optimize Code

Optimize your PHP loops:

Use:

for ($j=0, $max=sizeof($array), $s=0; $j<$max; $j++) {
    $s .= $array[$j];
}
echo $s;

Instead of:

for ($j=0; $j<sizeof($array); $j++) {
    echo $array[$j];
}

Use ob_start to start output buffering. This enables PHP to only write to the output stream once, saving significant overhead of sending information in small parts.

Read High Performance PHP by George Schlossnagle and use APD to profile any scripts which run slowly.

Read Performance Tuning PHP by Ilia Alshanetsky and implement any of the myriad suggestions to significantly improve your PHP and SQL code performance.

Notice: "unserialize() [<a href='function.unserialize'>function.unserialize</a>]: Error at offset 4036 of 4063 bytes" (...repeated 2 times)