Apache and other webserver tuning tips
Here are some tips to get your Apache webserver running to it's fullest potential. Many of the tips below are generic and
apply to any webserver not just Apache.
- Upgrade Apache to the newest version. You may want to try Apache 2.X.X.
It has worker threaded MPM and other speed enhancements. Benchmark both with your
site and see which one is better for you.
- In httpd.conf, set "HostNameLookups off" which avoids doing a reverse
DNS lookup on every visitor who hits your web site.
- In httpd.conf, a good rule of thumb for "MaxClients" is divide your total
RAM by 5 megabytes. So a server with 1GB of RAM could probably handle a MaxClients
setting of 200. You will have to test this. You might be have to set it higher or lower.
Setting it to high would be bad because each Apache process consumes some memory. You can only
fit a certain number processes in RAM before the web server begins swap things between
RAM and the hard drive in a horrid attempt to make things work. The result is a totally
unresponsive server with a thrashing hard disk. Suggestions from
Willy Tarreau a 2.4 kernel
maintainer in this area are the following.
"Observe the average per-process memory usage. Play with the MaxClient parameter to adjust the
maximum number of simultaneous processes so that the server never swaps. If there are large
differences between processes, it means that some requests produce large data sets, which are a real waste
when kept in memory. To solve this, you will need to tell Apache to make its processes die sooner, by
playing with the MaxRequestsPerChild value. The higher the value, the higher the memory usage. The
lower the value, the higher the CPU usage. Generally, values between 30 and 300 provide best results.
Then set the MinSpareServers and MaxSpareServers to values close to MaxClient so that the server does
not take too much time forking off new processes when the load comes in."
- In httpd.conf, busy websites should set "KeepAliveTimeout" low. Like to 2 seconds.
Keeping it low like this gives the client enough time to request all of the files needed for
a page without having to open multiple connections, yet will allow Apache to terminate the
connection soon enough to be able to handle many more clients than usual. Some people even
suggest turning keep-alives off totally. Willy Tarreau
a 2.4 kernel maintainer suggests this. He says "First, disable keep-alive. This is the nastiest
thing against performance. It was designed at a time sites were running NCSA httpd forked off inetd at
every request. All those forks were killing the servers, and keep-alive was a neat solution against this.
Right now, things have changed.
The servers do not fork at each connection and the cost of each new connection is minimal. Application
servers run a limited number of threads or processes, often because of either memory constraints, file
descriptor limits or locking overhead. Having a user monopolize a thread for seconds or even minutes
doing nothing is pure waste. The server will not use all of its CPU power, will consume insane amounts
of memory and users will wait for a connection to be free. If the keep-alive time is too short to
maintain the session between two clicks, it is useless. If it is long enough, then it means that the
servers will need roughly one process per simultaneous user, not counting the fact that most browsers
commonly establish 4 simultaneous sessions! Simply speaking, a site running keep-alive with an Apache-like
server has no chance of ever serving more than a few hundreds users at a time."
- Serve web graphics (such as jpg,png,gif files) or static files
light weight daemon like thttpd for this. Make sure the thttpd version
supports keep alives. Set your keep alives low (like 2-3 secs). Doing this
will free up Apache for handling the dynamic PHP/Perl stuff if you have it.
- Keep your Apache lean and mean. Compile Apache with as few modules as
needed. Before compiling (before your run make), edit the
/apache_1.x.x/src/Configuration file put a # in front of any AddModule
lines you don't need.
- If you don't need traffic logs (such as a site that only serves
graphics) then use the TransferLog directive in httpd.conf to redirect log
entries to /dev/null/
- Unless you insist on using .htaccess files to control access to
certain directories (there are other ways to do that), in access.conf (or
httpd.conf in newer versions of Apache) in the <Directory> section, set
"AllowOverride None" so that Apache will not bother looking for an
.htaccess file in each directory with each request.
- DO NOT serve web pages or write web traffic logs on a networked disk
drive (ie. NFS or SAMBA networked disks) -- read and write to local disk drives
only. NFS I/O operations incure huge overhead.
- DO NOT run Apache (httpd) via the tcpd wrapper in /etc/inetd.conf.
Apache can be started when the machine boots by either adding the startup
command to your rc.local file or by placing the httpd startup script to
your /etc/rc.d/rc3.d/ directory. If you want some mechanism to block
requests by IP address then use the "deny from" directive in the Apache's
conf files or in a .htacess file.
- Avoid using SSI tags if you can.
- In CGI scripts:
- File I/O: Open as few files as possible. Be sure to explicetly
close each opened file. Stop reading the file as soon as you found the
data you need. Consider structuring data files into fixed-length fields
and using read() function to skip ahead to just the part of the file you
need to read.
- Shell Commands: Call shell commands via their full path: eg. use
'/bin/date' instead of just `date` in a perl script.
- If your site is mostly CGI driven, by all means use mod_perl. See
http://perl.apache.org/. Mod_perl gives huge Perl speed increases.
- Perl programmers should study "Effective Perl Programming" by
Joseph N. Hall (an Addison Wesley book) and "The Perl Cookbook" by Tom
Christiansen (an O'Reilly book) -- two good texts for optimizing perl
code. For example, you can preallocate the memory for a hash that will
contain 256 items like so: "keys(%names) = 256;".
- Avoid having more than 1000 files in your web page directory.
Organize your web page files into subdirectories. The more files there
are in a directory, the longer it takes to locate that file during a
- Put as few graphics in your web pages as possible. Make sure each
image is run through an image compressor.
- Stress test your web site. Run Apache Benchmark program (called "ab")
in Apache's /bin or /sbin directory. The ab program will simulate heavy
traffic by running multiple simultaneous requests on any web page you want
for as long as you want then measures the load and response times. Very
useful for measuring the effects of your tuning efforts.
- The single biggest hardware issue affecting webserver performance is RAM.
A webserver should never ever have to swap, swapping increases the latency
of each request beyond a point that users consider "fast enough". This
causes users to hit stop and reload, further increasing the load.
You can, and should, control the MaxClients setting so that your server
does not spawn so many children it starts swapping.
- I should not have to say this but do not run any extra non-needed processes on
the server (X windows,mail,samba, or whatever).
- Turn on follow FollowSymLinks (Options -Indexes FollowSymLinks).
This saves a few io reads. Apache doesn't have to check if its a symlink,
it just goes ahead and traverses. Turn off SymLinksIfOwnerMatch to prevent
additional lstat() system calls from being made.
- Increase your kernel's tcp/ip write buffers so that most, if not all
generated pages can be written without blocking. If the page that
Apache generates fits in this buffer, then Apache's write() call
returns instantaneously, then Apache hands the socket over to
lingerd, logs the hit, and is immediately free for more work. If the
page doesn't fit, then write() blocks until the client has
acknowledged part of the data, which can take several seconds.
To change this, use the SendBufferSize directive from httpd.conf.
However, this directive cannot increase the buffer size past the
kernel limit. Changing this kernel limit is OS-specific.
Under Linux you can set it by echo'ing a larger number (eg. 131072)
into /proc/sys/net/core/wmem_max, before starting Apache. If you
change wmem_default as well as wmem_max, then the SendBufferSize
directive is not needed.
Disable ExtendedStatus unless you're actually debugging. Same goes for mod_info.
Use a reverse proxy cache in front of your server farm. This will return cached contents without hitting the application