perf-tuning.html revision cceb8f42ca47214278463c4042b32ff29ee162c6
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <meta name="generator" content="HTML Tidy, see www.w3.org" />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <!-- Background white, links blue (unvisited), navy (visited), red (active) -->
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <!--#include virtual="header.html" -->
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <strong>Warning:</strong> This document has not been fully updated
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync to take into account changes made in the 2.0 version of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Apache HTTP Server. Some of the information may still be
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync relevant, but please use it with care.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <li><a href="#hardware">Hardware and Operating System
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <li><a href="#runtime">Run-Time Configuration Issues</a></li>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <li><a href="#compiletime">Compile-Time Configuration
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <td valign="top"><strong>Related Modules</strong><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <a href="/mod/mod_status.html">mod_status</a><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <td valign="top"><strong>Related Directives</strong><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="/mod/core.html#allowoverride">AllowOverride</a><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="/mod/mod_dir.html#directoryindex">DirectoryIndex</a><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="/mod/core.html#hostnamelookups">HostnameLookups</a><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="/mod/core.html#enablemmap">EnableMMAP</a><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="/mod/core.html#keepalivetimeout">KeepAliveTimeout</a><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="/mod/prefork.html#maxspareservers">MaxSpareServers</a><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="/mod/prefork.html#mixspareservers">MinSpareServers</a><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (FollowSymLinks and FollowIfOwnerMatch)<br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="/mod/mpm_common.html#startservers">StartServers</a><br />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Apache 2.0 is a general-purpose webserver, designed to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync provide a balance of flexibility, portability, and performance.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Although it has not been designed specifically to set benchmark
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync records, Apache 2.0 is capable of high performance in many
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync real-world situations.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Compared to Apache 1.3, release 2.0 contains many additional
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync optimizations to increase throughput and scalability. Most of
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync these improvements are enabled by default. However, there are
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync compile-time and run-time configuration choices that can
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync significantly affect performance. This document describes the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync options that a server administrator can configure to tune the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync performance of an Apache 2.0 installation. Some of these
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync configuration options enable the httpd to better take advantage
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync of the capabilities of the hardware and OS, while others allow
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync the administrator to trade functionality for speed.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <h3><a id="hardware" name="hardware">Hardware and Operating
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>The single biggest hardware issue affecting webserver
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync performance is RAM. A webserver should never ever have to swap,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync swapping increases the latency of each request beyond a point
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync that users consider "fast enough". This causes users to hit
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync stop and reload, further increasing the load. You can, and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync should, control the <code>MaxClients</code> setting so that
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync your server does not spawn so many children it starts
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync swapping.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Beyond that the rest is mundane: get a fast enough CPU, a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fast enough network card, and fast enough disks, where "fast
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enough" is something that needs to be determined by
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync experimentation.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Operating system choice is largely a matter of local
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync concerns. But some guidelines that have proven generally
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync useful are:</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <li>Run the latest stable release and patchlevel of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync operating system that you choose. Many OS suppliers have
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync introduced significant performance improvements to their
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync TCP stacks and thread libraries in recent years.</li>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <li>If your OS supports a sendfile(2) system call, make
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sure you install the release and/or patches needed to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enable it. (With Linux, for example, this means using
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Linux 2.4 or later. For early releases of Solaris 8,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync you may need to apply a patch.) On systems where it
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync is available, sendfile enables Apache 2 to deliver
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static content faster and with lower CPU utilization.</li>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <h3><a id="runtime" name="runtime">Run-Time Configuration
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Prior to Apache 1.3, <code>HostnameLookups</code> defaulted
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync to On. This adds latency to every request because it requires a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync DNS lookup to complete before the request is finished. In
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Apache 1.3 this setting defaults to Off. However (1.3 or
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync later), if you use any <code>Allow from domain</code> or
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>Deny from domain</code> directives then you will pay for
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync a double reverse DNS lookup (a reverse, followed by a forward
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync to make sure that the reverse is not being spoofed). So for the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync highest performance avoid using these directives (it's fine to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync use IP addresses rather than domain names).</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Note that it's possible to scope the directives, such as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync within a <code><Location /server-status></code> section.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync In this case the DNS lookups are only performed on requests
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync matching the criteria. Here's an example which disables lookups
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync except for .html and .cgi files:</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncHostnameLookups off
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<Files ~ "\.(html|cgi)$">
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync HostnameLookups on
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</Files>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync But even still, if you just need DNS names in some CGIs you
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync could consider doing the <code>gethostbyname</code> call in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync specific CGIs that need it.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Similarly, if you need to have hostname information in your
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync server logs in order to generate reports of this information,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync you can postprocess your log file with <a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="/programs/logresolve.html">logresolve</a>, so that
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync these lookups can be done without making the client wait. It is
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync recommended that you do this postprocessing, and any other
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync statistical analysis of the log file, somewhere other than your
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync production web server machine, in order that this activity does
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync not adversely affect server performance.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Wherever in your URL-space you do not have an <code>Options
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync FollowSymLinks</code>, or you do have an <code>Options
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync SymLinksIfOwnerMatch</code> Apache will have to issue extra
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync system calls to check up on symlinks. One extra call per
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync filename component. For example, if you had:</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<Directory />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Options SymLinksIfOwnerMatch
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</Directory>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync and a request is made for the URI <code>/index.html</code>.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>/www/htdocs/index.html</code>. The results of these
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>lstats</code> are never cached, so they will occur on
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync every single request. If you really desire the symlinks
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync security checking you can do something like this:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<Directory />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Options FollowSymLinks
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</Directory>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Options -FollowSymLinks +SymLinksIfOwnerMatch
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</Directory>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync This at least avoids the extra checks for the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>DocumentRoot</code> path. Note that you'll need to add
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync similar sections if you have any <code>Alias</code> or
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>RewriteRule</code> paths outside of your document root.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync For highest performance, and no symlink protection, set
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>FollowSymLinks</code> everywhere, and never set
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Wherever in your URL-space you allow overrides (typically
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>.htaccess</code> files) Apache will attempt to open
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>.htaccess</code> for each filename component. For
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync example,</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<Directory />
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AllowOverride all
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</Directory>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync and a request is made for the URI <code>/index.html</code>.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Then Apache will attempt to open <code>/.htaccess</code>,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>/www/htdocs/.htaccess</code>. The solutions are similar
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync to the previous case of <code>Options FollowSymLinks</code>.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync For highest performance use <code>AllowOverride None</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync everywhere in your filesystem.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>If at all possible, avoid content-negotiation if you're
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync really interested in every last ounce of performance. In
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync practice the benefits of negotiation outweigh the performance
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync penalties. There's one case where you can speed up the server.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Instead of using a wildcard such as:</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncDirectoryIndex index
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Use a complete list of options:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncDirectoryIndex index.cgi index.pl index.shtml index.html
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync where you list the most common choice first.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Also note that explicitly creating a <code>type-map</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync file provides better performance than using
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>MultiViews</code>, as the necessary information can be
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync determined by reading this single file, rather than having to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync scan the directory for files.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>In situations where Apache 2.0 needs to look at the contents
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync of a file being delivered--for example, when doing server-side-include
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync processing--it normally memory-maps the file if the OS supports
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync some form of mmap(2).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>On some platforms, this memory-mapping improves performance.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync However, there are cases where memory-mapping can hurt the performance
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync or even the stability of the httpd:</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <li>On some operating systems, mmap does not scale as well as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync read(2) when the number of CPUs increases. On multiprocessor
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Solaris servers, for example, Apache 2.0 sometimes delivers
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync server-parsed files faster when mmap is disabled.</li>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <li>If you memory-map a file located on an NFS-mounted filesystem
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync and a process on another NFS client machine deletes or truncates
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync the file, your process may get a bus error the next time it tries
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync to access the mapped file content.</li>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>For installations where either of these factors applies, you
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync should use <code>EnableMMAP off</code> to disable the memory-mapping
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync of delivered files. (Note: This directive can be overridden on
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync a per-directory basis.)</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Prior to Apache 1.3 the <code>MinSpareServers</code>,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>MaxSpareServers</code>, and <code>StartServers</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync settings all had drastic effects on benchmark results. In
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync particular, Apache required a "ramp-up" period in order to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync reach a number of children sufficient to serve the load being
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync applied. After the initial spawning of
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>StartServers</code> children, only one child per second
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync would be created to satisfy the <code>MinSpareServers</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync setting. So a server being accessed by 100 simultaneous
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync clients, using the default <code>StartServers</code> of 5 would
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync take on the order 95 seconds to spawn enough children to handle
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync the load. This works fine in practice on real-life servers,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync because they aren't restarted frequently. But does really
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync poorly on benchmarks which might only run for ten minutes.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>The one-per-second rule was implemented in an effort to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync avoid swamping the machine with the startup of new children. If
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync the machine is busy spawning children it can't service
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync requests. But it has such a drastic effect on the perceived
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync performance of Apache that it had to be replaced. As of Apache
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 1.3, the code will relax the one-per-second rule. It will spawn
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync one, wait a second, then spawn two, wait a second, then spawn
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync four, and it will continue exponentially until it is spawning
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 32 children per second. It will stop whenever it satisfies the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>This appears to be responsive enough that it's almost
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync unnecessary to twiddle the <code>MinSpareServers</code>,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>MaxSpareServers</code> and <code>StartServers</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync knobs. When more than 4 children are spawned per second, a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync message will be emitted to the <code>ErrorLog</code>. If you
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync see a lot of these errors then consider tuning these settings.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Use the <code>mod_status</code> output as a guide.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Related to process creation is process death induced by the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>MaxRequestsPerChild</code> setting. By default this is 0,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync which means that there is no limit to the number of requests
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync handled per child. If your configuration currently has this set
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync to some very low number, such as 30, you may want to bump this
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync up significantly. If you are running SunOS or an old version of
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Solaris, limit this to 10000 or so because of memory leaks.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>When keep-alives are in use, children will be kept busy
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync doing nothing waiting for more requests on the already open
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync connection. The default <code>KeepAliveTimeout</code> of 15
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync seconds attempts to minimize this effect. The tradeoff here is
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync between network bandwidth and server resources. In no event
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync should you raise this above about 60 seconds, as <a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="http://www.research.digital.com/wrl/techreports/abstracts/95.4.html">
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <h3><a id="compiletime" name="compiletime">Compile-Time
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>If you include <code>mod_status</code> and you also set
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>ExtendedStatus On</code> when building and running
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Apache, then on every request Apache will perform two calls to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>gettimeofday(2)</code> (or <code>times(2)</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync depending on your operating system), and (pre-1.3) several
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync extra calls to <code>time(2)</code>. This is all done so that
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync the status report contains timing indications. For highest
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync performance, set <code>ExtendedStatus off</code> (which is the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync default).</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>This discusses a shortcoming in the Unix socket API. Suppose
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync your web server uses multiple <code>Listen</code> statements to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync listen on either multiple ports or multiple addresses. In order
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync to test each socket to see if a connection is ready Apache uses
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>select(2)</code>. <code>select(2)</code> indicates that a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync socket has <em>zero</em> or <em>at least one</em> connection
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync waiting on it. Apache's model includes multiple children, and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync all the idle ones test for new connections at the same time. A
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync naive implementation looks something like this (these examples
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync do not match the code, they're contrived for pedagogical
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync purposes):</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fd_set accept_fds;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync FD_ZERO (&accept_fds);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (i = first_socket; i <= last_socket; ++i) {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync FD_SET (i, &accept_fds);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc < 1) continue;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync new_connection = -1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (i = first_socket; i <= last_socket; ++i) {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (FD_ISSET (i, &accept_fds)) {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync new_connection = accept (i, NULL, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (new_connection != -1) break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (new_connection != -1) break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync process the new_connection;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync But this naive implementation has a serious starvation problem.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Recall that multiple children execute this loop at the same
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync time, and so multiple children will block at
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>select</code> when they are in between requests. All
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync those blocked children will awaken and return from
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>select</code> when a single request appears on any socket
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (the number of children which awaken varies depending on the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync operating system and timing issues). They will all then fall
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync down into the loop and try to <code>accept</code> the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync connection. But only one will succeed (assuming there's still
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync only one connection ready), the rest will be <em>blocked</em>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync in <code>accept</code>. This effectively locks those children
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync into serving requests from that one socket and no other
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync sockets, and they'll be stuck there until enough new requests
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync appear on that socket to wake them all up. This starvation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync problem was first documented in <a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="http://bugs.apache.org/index/full/467">PR#467</a>. There
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync are at least two solutions.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>One solution is to make the sockets non-blocking. In this
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case the <code>accept</code> won't block the children, and they
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync will be allowed to continue immediately. But this wastes CPU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync time. Suppose you have ten idle children in
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>select</code>, and one connection arrives. Then nine of
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync those children will wake up, try to <code>accept</code> the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync connection, fail, and loop back into <code>select</code>,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync accomplishing nothing. Meanwhile none of those children are
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync servicing requests that occurred on other sockets until they
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync get back up to the <code>select</code> again. Overall this
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync solution does not seem very fruitful unless you have as many
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync idle CPUs (in a multiprocessor box) as you have idle children,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync not a very likely situation.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Another solution, the one used by Apache, is to serialize
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync entry into the inner loop. The loop looks like this
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (differences highlighted):</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fd_set accept_fds;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync FD_ZERO (&accept_fds);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (i = first_socket; i <= last_socket; ++i) {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync FD_SET (i, &accept_fds);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc < 1) continue;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync new_connection = -1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (i = first_socket; i <= last_socket; ++i) {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (FD_ISSET (i, &accept_fds)) {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync new_connection = accept (i, NULL, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (new_connection != -1) break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (new_connection != -1) break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync process the new_connection;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <a id="serialize" name="serialize">The functions</a>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>accept_mutex_on</code> and <code>accept_mutex_off</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync implement a mutual exclusion semaphore. Only one child can have
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync the mutex at any time. There are several choices for
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync implementing these mutexes. The choice is defined in
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>src/include/ap_config.h</code> (1.3 or later). Some
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync architectures do not have any locking choice made, on these
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync architectures it is unsafe to use multiple <code>Listen</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync directives.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <dd>This method uses the <code>flock(2)</code> system call to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync lock a lock file (located by the <code>LockFile</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync directive).</dd>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <dd>This method uses the <code>fcntl(2)</code> system call to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync lock a lock file (located by the <code>LockFile</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync directive).</dd>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <dt><code>USE_SYSVSEM_SERIALIZED_ACCEPT</code></dt>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <dd>(1.3 or later) This method uses SysV-style semaphores to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync implement the mutex. Unfortunately SysV-style semaphores have
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync some bad side-effects. One is that it's possible Apache will
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync die without cleaning up the semaphore (see the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>ipcs(8)</code> man page). The other is that the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync semaphore API allows for a denial of service attack by any
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync CGIs running under the same uid as the webserver
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (<em>i.e.</em>, all CGIs, unless you use something like
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync suexec or cgiwrapper). For these reasons this method is not
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync used on any architecture except IRIX (where the previous two
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync are prohibitively expensive on most IRIX boxes).</dd>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <dd>(1.3 or later) This method is only available on IRIX, and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uses <code>usconfig(2)</code> to create a mutex. While this
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync method avoids the hassles of SysV-style semaphores, it is not
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync the default for IRIX. This is because on single processor
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync IRIX boxes (5.3 or 6.2) the uslock code is two orders of
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync magnitude slower than the SysV-semaphore code. On
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync multi-processor IRIX boxes the uslock code is an order of
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync magnitude faster than the SysV-semaphore code. Kind of a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync messed up situation. So if you're using a multiprocessor IRIX
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync box then you should rebuild your webserver with
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <dt><code>USE_PTHREAD_SERIALIZED_ACCEPT</code></dt>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <dd>(1.3 or later) This method uses POSIX mutexes and should
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync work on any architecture implementing the full POSIX threads
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync specification, however appears to only work on Solaris (2.5
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync or later), and even then only in certain configurations. If
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync you experiment with this you should watch out for your server
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync hanging and not responding. Static content only servers may
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync work just fine.</dd>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>If your system has another method of serialization which
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync isn't in the above list then it may be worthwhile adding code
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for it (and submitting a patch back to Apache).</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Another solution that has been considered but never
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync implemented is to partially serialize the loop -- that is, let
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync in a certain number of processes. This would only be of
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync interest on multiprocessor boxes where it's possible multiple
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync children could run simultaneously, and the serialization
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync actually doesn't take advantage of the full bandwidth. This is
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync a possible area of future investigation, but priority remains
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync low because highly parallel web servers are not the norm.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Ideally you should run servers without multiple
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>Listen</code> statements if you want the highest
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync performance. But read on.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>The above is fine and dandy for multiple socket servers, but
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync what about single socket servers? In theory they shouldn't
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync experience any of these same problems because all children can
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync just block in <code>accept(2)</code> until a connection
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync arrives, and no starvation results. In practice this hides
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync almost the same "spinning" behaviour discussed above in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync non-blocking solution. The way that most TCP stacks are
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync implemented, the kernel actually wakes up all processes blocked
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync in <code>accept</code> when a single connection arrives. One of
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync those processes gets the connection and returns to user-space,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync the rest spin in the kernel and go back to sleep when they
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync discover there's no connection for them. This spinning is
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync hidden from the user-land code, but it's there nonetheless.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync This can result in the same load-spiking wasteful behaviour
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync that a non-blocking solution to the multiple sockets case
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>For this reason we have found that many architectures behave
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync more "nicely" if we serialize even the single socket case. So
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync this is actually the default in almost all cases. Crude
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync experiments under Linux (2.0.30 on a dual Pentium pro 166
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync w/128Mb RAM) have shown that the serialization of the single
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync socket case causes less than a 3% decrease in requests per
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync second over unserialized single-socket. But unserialized
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync single-socket showed an extra 100ms latency on each request.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync This latency is probably a wash on long haul lines, and only an
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync issue on LANs. If you want to override the single socket
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync serialization you can define
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>SINGLE_LISTEN_UNSERIALIZED_ACCEPT</code> and then
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync single-socket servers will not serialize at all.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-connection-00.txt">
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync draft-ietf-http-connection-00.txt</a> section 8, in order for
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync an HTTP server to <strong>reliably</strong> implement the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync protocol it needs to shutdown each direction of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync communication independently (recall that a TCP connection is
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bi-directional, each half is independent of the other). This
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fact is often overlooked by other servers, but is correctly
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync implemented in Apache as of 1.2.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>When this feature was added to Apache it caused a flurry of
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync problems on various versions of Unix because of a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync shortsightedness. The TCP specification does not state that the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync FIN_WAIT_2 state has a timeout, but it doesn't prohibit it. On
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync systems without the timeout, Apache 1.2 induces many sockets
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync stuck forever in the FIN_WAIT_2 state. In many cases this can
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync be avoided by simply upgrading to the latest TCP/IP patches
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync supplied by the vendor. In cases where the vendor has never
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync released patches (<em>i.e.</em>, SunOS4 -- although folks with
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync a source license can patch it themselves) we have decided to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync disable this feature.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>There are two ways of accomplishing this. One is the socket
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync option <code>SO_LINGER</code>. But as fate would have it, this
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync has never been implemented properly in most TCP/IP stacks. Even
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync on those stacks with a proper implementation (<em>i.e.</em>,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Linux 2.0.31) this method proves to be more expensive (cputime)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync than the next solution.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>For the most part, Apache implements this in a function
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>http_main.c</code>). The function looks roughly like
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync void lingering_close (int s)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char junk_buffer[2048];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* shutdown the sending side */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync shutdown (s, 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync signal (SIGALRM, lingering_death);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync alarm (30);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync select (s for reading, 2 second timeout);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (error) break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (s is ready for reading) {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (read (s, junk_buffer, sizeof (junk_buffer)) <= 0) {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* just toss away whatever is here */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync This naturally adds some expense at the end of a connection,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync but it is required for a reliable implementation. As HTTP/1.1
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync becomes more prevalent, and all connections are persistent,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync this expense will be amortized over more requests. If you want
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync to play with fire and disable this feature you can define
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>NO_LINGCLOSE</code>, but this is not recommended at all.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync In particular, as HTTP/1.1 pipelined persistent connections
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync come into use <code>lingering_close</code> is an absolute
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync necessity (and <a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync href="http://www.w3.org/Protocols/HTTP/Performance/Pipeline.html">
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pipelined connections are faster</a>, so you want to support
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Apache's parent and children communicate with each other
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync through something called the scoreboard. Ideally this should be
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync implemented in shared memory. For those operating systems that
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync we either have access to, or have been given detailed ports
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for, it typically is implemented using shared memory. The rest
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync default to using an on-disk file. The on-disk file is not only
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync slow, but it is unreliable (and less featured). Peruse the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>src/main/conf.h</code> file for your architecture and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync look for either <code>USE_MMAP_SCOREBOARD</code> or
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>USE_SHMGET_SCOREBOARD</code>. Defining one of those two
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (as well as their companions <code>HAVE_MMAP</code> and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>HAVE_SHMGET</code> respectively) enables the supplied
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync shared memory code. If your system has another type of shared
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync memory, edit the file <code>src/main/http_main.c</code> and add
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync the hooks necessary to use it in Apache. (Send us back a patch
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync too please.)</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Historical note: The Linux port of Apache didn't start to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync use shared memory until version 1.2 of Apache. This oversight
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync resulted in really poor and unreliable behaviour of earlier
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync versions of Apache on Linux.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>If you have no intention of using dynamically loaded modules
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (you probably don't if you're reading this and tuning your
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync server for every last ounce of performance) then you should add
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <code>-DDYNAMIC_MODULE_LIMIT=0</code> when building your
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync server. This will save RAM that's allocated only for supporting
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dynamically loaded modules.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <h3><a id="trace" name="trace">Appendix: Detailed Analysis of a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Here is a system call trace of Apache 2.0.38 with the worker MPM
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync on Solaris 8. This trace was collected using:</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<code>truss -l -p <i>httpd_child_pid</i></code>.</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>The <code>-l</code> option tells truss to log the ID of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LWP (lightweight process--Solaris's form of kernel-level thread)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync that invokes each system call.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>Other systems may have different system call tracing utilities
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync such as <code>strace</code>, <code>ktrace</code>, or <code>par</code>.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync They all produce similar output.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <p>In this trace, a client has requested a 10KB static file
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync from the httpd. Traces of non-static requests or requests
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync with content negotiation look wildly different (and quite ugly
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync in some cases).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync <blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/67: accept(3, 0x00200BEC, 0x00200C0C, 1) (sleeping...)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/67: accept(3, 0x00200BEC, 0x00200C0C, 1) = 9
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>In this trace, the listener thread is running within LWP #67.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>Note the lack of accept(2) serialization. On this particular
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncplatform, the worker MPM uses an unserialized accept by default
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncunless it is listening on multiple ports.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: lwp_park(0x00000000, 0) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/67: lwp_unpark(65, 1) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>Upon accepting the connection, the listener thread wakes up
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynca worker thread to do the request processing. In this trace,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncthe worker thread that handles the request is mapped to LWP #65.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: getsockname(9, 0x00200BA4, 0x00200BC4, 1) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>In order to implement virtual hosts, Apache needs to know
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncthe local socket address used to accept the connection. It
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncis possible to eliminate this call in many situations (such
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncas when there are no virtual hosts, or when <code>Listen</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdirectives are used which do not have wildcard addresses). But
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncno effort has yet been made to do these optimizations. </p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: brk(0x002170E8) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: brk(0x002190E8) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>The brk(2) calls allocate memory from the heap. It is rare
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncto see these in a system call trace, because the httpd uses
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<code>apr_bucket_alloc</code>) for most request processing.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncIn this trace, the httpd has just been started, so it must
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynccall malloc(3) to get the blocks of raw memory with which
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncto create the custom memory allocators.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: fcntl(9, F_GETFL, 0x00000000) = 2
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: fstat64(9, 0xFAF7B818) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B910, 2190656) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: fstat64(9, 0xFAF7B818) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B914, 2190656) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: setsockopt(9, 65535, 8192, 0xFAF7B918, 4, 2190656) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: fcntl(9, F_SETFL, 0x00000082) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>Next, the worker thread puts the connection to the client (file
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncdescriptor 9) in non-blocking mode. The setsockopt(2) and getsockopt(2)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynccalls are a side-effect of how Solaris's libc handles fcntl(2) on sockets.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: read(9, " G E T / 1 0 k . h t m".., 8000) = 97
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>The worker thread reads the request from the client.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: stat("/var/httpd/apache/httpd-8999/htdocs/10k.html", 0xFAF7B978) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: open("/var/httpd/apache/httpd-8999/htdocs/10k.html", O_RDONLY) = 10
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>This httpd has been configured with <code>Options FollowSymLinks</code>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncand <code>AllowOverride None</code>. Thus it doesn't need to lstat(2)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynceach directory in the path leading up to the requested file, nor
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynccheck for <code>.htaccess</code> files. It simply calls stat(2) to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncverify that the file: 1) exists, and 2) is a regular file, not a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: sendfilev(0, 9, 0x00200F90, 2, 0xFAF7B53C) = 10269
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>In this example, the httpd is able to send the HTTP response
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncheader and the requested file with a single sendfilev(2) system call.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncSendfile semantics vary among operating systems. On some other
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncsystems, it is necessary to do a write(2) or writev(2) call to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncsend the headers before calling sendfile(2).</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: write(4, " 1 2 7 . 0 . 0 . 1 - ".., 78) = 78
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>This write(2) call records the request in the access log.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncNote that one thing missing from this trace is a time(2) call.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncUnlike Apache 1.3, Apache 2.0 uses gettimeofday(3) to look up
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncthe time. On some operating systems, like Linux or Solaris,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncgettimeofday has an optimized implementation that doesn't require
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncas much overhead as a typical system call.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: shutdown(9, 1, 1) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: poll(0xFAF7B980, 1, 2000) = 1
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: read(9, 0xFAF7BC20, 512) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: close(9) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>The worker thread does a lingering close of the connection.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: close(10) = 0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/65: lwp_park(0x00000000, 0) (sleeping...)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>Finally the worker thread closes the file that it has just delivered
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncand blocks until the listener assigns it another connection.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/67: accept(3, 0x001FEB74, 0x001FEB94, 1) (sleeping...)</pre>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync<p>Meanwhile, the listener thread is able to accept another connection
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncas soon as it has dispatched this connection to a worker thread (subject
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncto some flow-control logic in the worker MPM that throttles the listener
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncif all the available workers are busy). Though it isn't apparent from
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncthis trace, the next accept(2) can (and usually does, under high load
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncconditions) occur in parallel with the worker thread's handling of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncjust-accepted connection.</p>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync</blockquote>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync </blockquote>