Introduction
This tutorial is covering the web server performance tunings on MySQL, PHP and Apache,WordPress and BuddyPress or general web hosting purpose, the tuning example is based on CentOS 5.
The key of the following performance tuning is focus on memory and caching, most of people host a web site or forum or blog without any tunings or even use the all out-of-box setting.
OS Tuning
/etc/sysctl.conf
Share Memory
1
2
3
4
| #2GBkernel.shmmax = 2147483648kernel.shmall = 2147483648fs.file-max = 16384 |
MySQL Tuning
MySQL default setting is very inefficient, here is a baseline for a web access by >200 concurrent users running with Joomla, wordpress, phpbb..etc. DB query cache is quite important for a large website, it reduce lot of disk I/O, minimize the wait time for every of same query.
/etc/my.cnf
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| [mysqld]key_buffer = 64Msort_buffer = 1Mjoin_buffer = 1Mmax_allowed_packet = 8Mmax_heap_table_size = 16Mtable_cache = 1024sort_buffer_size = 8Mread_buffer_size = 1Mread_rnd_buffer_size = 768Kmyisam_sort_buffer_size = 48Mthread_cache_size = 512query_cache_type = 1query_cache_limit = 4Mquery_cache_size = 64Mtmp_table_size = 16M# Try number of CPU's*2 for thread_concurrencythread_concurrency = 4max_write_lock_count = 1 #To force MySQL to temporarily elevate the priority of all SELECT statements that are waiting for a table after a specific number of inserts to the table occur. This allows READ locks after a certain number of WRITE locks.low_priority_updates = 1[isamchk]key_buffer = 64Msort_buffer = 64Mread_buffer = 16Mwrite_buffer = 16M[myisamchk]key_buffer = 64Msort_buffer = 64Mread_buffer = 16Mwrite_buffer = 16M |
Another good starting point for a WordPress hosting, appox uses 500MB – 1.2GB memory
01
02
03
04
05
06
07
08
09
10
11
| key_buffer = 64Msort_buffer = 1Mjoin_buffer = 12Mmax_allowed_packet = 8Mmax_heap_table_size = 160Mtable_cache = 3096thread_cache_size = 4query_cache_limit = 512Mquery_cache_size = 96Mtmp_table_size = 160Minnodb_buffer_pool_size = 26M |
Please read the follwoing topic for MySQL Tuning suggestion
Apache Web Server Tuning
Default MPM setting is prefork, which consumes a lot of memory when your web site under stress. So considering to activate worker MPM is better idea to double up your current web capacity without adding additional hardware.
Switching to worker MPM with PHP will not gain any performance boost if you don’t have proper object cache or page cache, however running PHP apache module with prefork MPM is faster then worker MPM in CGI mode.
http://www.serverwatch.com/tutorials/article.php/3436911/Optimizing-Apache-Server-Performance.htm
/etc/sysconfig/httpd
http://www.serverwatch.com/tutorials/article.php/3436911/Optimizing-Apache-Server-Performance.htm
/etc/sysconfig/httpd
1
| HTTPD=/usr/sbin/httpd.worker |
/etc/httpd/conf/httpd.conf
1
2
3
4
5
6
| StartServers 6MaxClients 300MinSpareThreads 25MaxSpareThreads 75ThreadsPerChild 25MaxRequestsPerChild 2000 |
Apache Prefork vs Worker
http://www.camelrichard.org/apache-prefork-vs-worker
http://www.camelrichard.org/apache-prefork-vs-worker
Running PHP5 with Apache worker MPM
When you switched to worker MPM, you may immediately encountered errors on PHP module. Yes, you need to change the php from apache module to PHP CGI, it’s PHP thread safe issues on worker MPM.
Install FastCGI
1
2
3
4
| wget "http://www.fastcgi.com/dist/mod_fastcgi-current.tar.gz"cp Makefile.AP2 Makefilemake top_dir=/usr/lib64/httpd ## or make top_dir=/usr/lib/httpd ## for 32bitmake install |
Add the LoadModule entry in /etc/httpd/conf/httpd.conf
1
| LoadModule fastcgi_module modules/mod_fastcgi.so |
Add a php.fcgi file in /var/www/cgi-bin/
1
2
3
4
5
6
7
| #!/bin/shPHP_FCGI_CHILDREN=4export PHP_FCGI_CHILDRENPHP_FCGI_MAX_REQUESTS=0export PHP_FCGI_MAX_REQUESTSumask 0022exec /usr/bin/php-cgi -d apc.shm_size=96M |
and
1
| chmod +x /var/www/cgi-bin/php.fcgi |
set PHP_FCGI_CHILDREN=4 or higher depends on your CPU power
set PHP_FCGI_MAX_REQUESTS=10000 # or 0, to respawn the process after reaching maximum number of request, it prevent php having memory leak without a refreshment. On the other hand some application will having 500 internal errors because the process gone but the session wasn’t. Meanwhile, you do set it to 0 or a very high value, and closely monitor the php-cgi process that not ate up all memory.
set PHP_FCGI_MAX_REQUESTS=10000 # or 0, to respawn the process after reaching maximum number of request, it prevent php having memory leak without a refreshment. On the other hand some application will having 500 internal errors because the process gone but the session wasn’t. Meanwhile, you do set it to 0 or a very high value, and closely monitor the php-cgi process that not ate up all memory.
Setting apc.shm_size=96M
a predictable memory size likely will be 96M x 4 and maximum memory = php memory limit x 4
a predictable memory size likely will be 96M x 4 and maximum memory = php memory limit x 4
For your reference, WordPress with BuddyPress consume quite much memory, in various test, it require about 48-60MB php memory, therefore to get a good performance for BP, you better set the cache size not fewer then 80M.
Disable mod php settings in /etc/httpd/conf.d
1
| mv php.conf php.conf.disabled |
Create new config php-cgi.conf in /etc/httpd/conf.d
maxClassProcesses parameter is very important, anything > 1 will let you lose object cache, so to get best the performance, use PHP_FCGI_CHILDREN instead of parent process. Unless you told me you don’t use object cache.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
| LoadModule fastcgi_module modules/mod_fastcgi.soFastCgiConfig -idle-timeout 60 -maxClassProcesses 1 -maxProcesses 50FastCgiWrapper OnDirectoryIndex index.phpAddHandler php5-fcgi .phpAddHandler php5-fcgi .fcgiAction php5-fcgi /cgi-bin/php.fcgi<Location "/cgi-bin/php.fcgi"> Order Deny,Allow Deny from All Allow from env=REDIRECT_STATUS #Protect from direct access of this script Options ExecCGI SetHandler fastcgi-script</Location> |
PHP 5.2
If you still running php 5.0, please upgrade it.
Put the following lines into /etc/yum.repos.d/c5-testing.repos
Put the following lines into /etc/yum.repos.d/c5-testing.repos
1
2
3
4
5
6
| [c5-testing]name=CentOS-5 Testingbaseurl=http://dev.centos.org/centos/$releasever/testing/$basearch/enabled=1gpgcheck=1gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing |
remove all existing PHP5 and PECL rpm packages and run
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
| yum install \php \php-mbstring \php-ldap \php-mysql \php-mcrypt \php-cli \php-gd \php-xml \php-devel \php-bcmath \php-xmlrpc \php-common \php-soap \php-pdo \php-imap |
Install memcached
memcached is a high-performance memory object caching system intended to speed up dynamic web applications by alleviating database load.
1
| yum install memcached |
/etc/sysconfig/memcached
1
2
3
4
5
| PORT="11211"USER="nobody"MAXCONN="1024"CACHESIZE="256"OPTIONS="" |
Install PHP memcache.so
1
2
3
4
5
| cdphpize./configure --enable-memcachemakecp memcache.so /usr/lib64/php/modules/ |
Enable it in /etc/php.ini
1
| extension=memcache.so |
Install eAccelerator
wget "http://bart.eaccelerator.net/source/0.9.5.2/eaccelerator-0.9.5.2.tar.bz2"tar xvfj eaccelerator-0.9.5.2.tar.bz2cd eaccelerator-0.9.5.2phpize./configuremakemake installmkdir /tmp/eacceleratorchmod 777 /tmp/eaccelerator/etc/php.ini
[eaccelerator]zend_extension="/usr/lib64/php/modules/eaccelerator.so"eaccelerator.shm_size="64"eaccelerator.cache_dir="/tmp/eaccelerator"eaccelerator.enable="1"eaccelerator.optimizer="1"eaccelerator.check_mtime="1"eaccelerator.debug="0"eaccelerator.filter=""eaccelerator.shm_max="0"eaccelerator.shm_ttl="0"eaccelerator.shm_prune_period="0"eaccelerator.shm_only="0"eaccelerator.compress="1"eaccelerator.compress_level="9"eaccelerator.log_file = "/var/log/httpd/eaccelerator_log"http://www.php.ph/2007/12/21/centos-5-eaccelerator-installation/
Install APC
1
| pecl install apc |
Create a apc.ini config file in /etc/php.d/
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| ; /etc/php.d/apc.iniextension=apc.soapc.enabled="1"apc.shm_segments="1"apc.num_files_hint="1024"apc.ttl="7200"apc.user_ttl="7200"apc.gc_ttl="3600"apc.cache_by_default="1";apc.filters=""apc.slam_defense="0"apc.file_update_protection="2"apc.enable_cli="0"apc.max_file_size="1M"apc.stat="1"apc.write_lock="1"apc.report_autofilter="0"apc.include_once_override="0"apc.rfc1867="0"apc.rfc1867_prefix="upload_"apc.rfc1867_name="APC_UPLOAD_PROGRESS"apc.rfc1867_freq="0"apc.localcache="0"apc.localcache.size="512"apc.coredump_unmap="0";apc.shm_size=128M ;;;;;;;; Don't define share memory here, we'll do it in php wrapperapc.mmap_file_mask="/tmp/apcphp5.XXXXXX"apc.mmap_address=703687441776 |
Compress PHP output using ob_gzhandler
/etc/php.ini
1
2
3
| output_buffering = Onoutput_handler = ob_gzhandlerzlib.output_compression = Off |
Apache deflate for contents compression
The mod_deflate module provides the DEFLATE output filter that allows output from your server to be compressed before being sent to the client over the network, it helps to improve contents transfer over network, it doesn’t really helps to speed up your web, but it speed up the content transfer flow and gain more user access through the same network without additional bandwidth.
1
2
3
4
5
6
7
8
| # Set compression for: html,txt,xml,js,cssAddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/javascript text/css application/x-javascript# Deactivate compression for buggy browsersBrowserMatch ^Mozilla/4 gzip-only-text/htmlBrowserMatch ^Mozilla/4.0[678] no-gzipBrowserMatch bMSIE !no-gzip !gzip-only-text/html# Set header information for proxiesHeader append Vary User-Agent |
Recommended WordPress Plugins
wp-config.php
1
2
| define( 'WP_CACHE', true );define(’WP_POST_REVISIONS’, false); |
Conclusion
Always measure the performance with or without tuning, the tuning parameters is just case by case. Some PHP scripts running with Fastcgi isn’t as fast as module, so you have to compared it side by side.
Your blog has given me that thing which I never expect to get from all over the websites. Nice post guys!
ReplyDelete