1<?xml version="1.0" encoding="ISO-8859-1"?>
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head><!--
4        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5              This file is generated from xml source: DO NOT EDIT
6        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7      -->
8<title>Apache Performance Tuning - Apache HTTP Server</title>
9<link href="/style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
10<link href="/style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
11<link href="/style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" /><link rel="stylesheet" type="text/css" href="/style/css/prettify.css" />
12<script src="/style/scripts/prettify.js" type="text/javascript">
13</script>
14
15<link href="/images/favicon.ico" rel="shortcut icon" /></head>
16<body id="manual-page"><div id="page-header">
17<p class="menu"><a href="/mod/">Modules</a> | <a href="/mod/directives.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="/glossary.html">Glossary</a> | <a href="/sitemap.html">Sitemap</a></p>
18<p class="apache">Apache HTTP Server Version 2.2</p>
19<img alt="" src="/images/feather.gif" /></div>
20<div class="up"><a href="./"><img title="&lt;-" alt="&lt;-" src="/images/left.gif" /></a></div>
21<div id="path">
22<a href="http://www.apache.org/">Apache</a> &gt; <a href="http://httpd.apache.org/">HTTP Server</a> &gt; <a href="http://httpd.apache.org/docs/">Documentation</a> &gt; <a href="../">Version 2.2</a> &gt; <a href="./">Miscellaneous Documentation</a></div><div id="page-content"><div id="preamble"><h1>Apache Performance Tuning</h1>
23<div class="toplang">
24<p><span>Available Languages: </span><a href="/en/misc/perf-tuning.html" title="English">&nbsp;en&nbsp;</a> |
25<a href="/ko/misc/perf-tuning.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a> |
26<a href="/tr/misc/perf-tuning.html" hreflang="tr" rel="alternate" title="T�rk�e">&nbsp;tr&nbsp;</a></p>
27</div>
28
29
30    <p>Apache 2.x is a general-purpose webserver, designed to
31    provide a balance of flexibility, portability, and performance.
32    Although it has not been designed specifically to set benchmark
33    records, Apache 2.x is capable of high performance in many
34    real-world situations.</p>
35
36    <p>Compared to Apache 1.3, release 2.x contains many additional
37    optimizations to increase throughput and scalability. Most of
38    these improvements are enabled by default. However, there are
39    compile-time and run-time configuration choices that can
40    significantly affect performance. This document describes the
41    options that a server administrator can configure to tune the
42    performance of an Apache 2.x installation. Some of these
43    configuration options enable the httpd to better take advantage
44    of the capabilities of the hardware and OS, while others allow
45    the administrator to trade functionality for speed.</p>
46
47  </div>
48<div id="quickview"><ul id="toc"><li><img alt="" src="/images/down.gif" /> <a href="#hardware">Hardware and Operating System Issues</a></li>
49<li><img alt="" src="/images/down.gif" /> <a href="#runtime">Run-Time Configuration Issues</a></li>
50<li><img alt="" src="/images/down.gif" /> <a href="#compiletime">Compile-Time Configuration Issues</a></li>
51<li><img alt="" src="/images/down.gif" /> <a href="#trace">Appendix: Detailed Analysis of a Trace</a></li>
52</ul><ul class="seealso"><li><a href="#comments_section">Comments</a></li></ul></div>
53<div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
54<div class="section">
55<h2><a name="hardware" id="hardware">Hardware and Operating System Issues</a></h2>
56
57    
58
59    <p>The single biggest hardware issue affecting webserver
60    performance is RAM. A webserver should never ever have to swap,
61    as swapping increases the latency of each request beyond a point
62    that users consider "fast enough". This causes users to hit
63    stop and reload, further increasing the load. You can, and
64    should, control the <code class="directive"><a href="/mod/mpm_common.html#maxclients">MaxClients</a></code> setting so that your server
65    does not spawn so many children it starts swapping. This procedure
66    for doing this is simple: determine the size of your average Apache
67    process, by looking at your process list via a tool such as
68    <code>top</code>, and divide this into your total available memory,
69    leaving some room for other processes.</p>
70
71    <p>Beyond that the rest is mundane: get a fast enough CPU, a
72    fast enough network card, and fast enough disks, where "fast
73    enough" is something that needs to be determined by
74    experimentation.</p>
75
76    <p>Operating system choice is largely a matter of local
77    concerns. But some guidelines that have proven generally
78    useful are:</p>
79
80    <ul>
81      <li>
82        <p>Run the latest stable release and patchlevel of the
83        operating system that you choose. Many OS suppliers have
84        introduced significant performance improvements to their
85        TCP stacks and thread libraries in recent years.</p>
86      </li>
87
88      <li>
89        <p>If your OS supports a <code>sendfile(2)</code> system
90        call, make sure you install the release and/or patches
91        needed to enable it. (With Linux, for example, this means
92        using Linux 2.4 or later. For early releases of Solaris 8,
93        you may need to apply a patch.) On systems where it is
94        available, <code>sendfile</code> enables Apache 2 to deliver
95        static content faster and with lower CPU utilization.</p>
96      </li>
97    </ul>
98
99  </div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
100<div class="section">
101<h2><a name="runtime" id="runtime">Run-Time Configuration Issues</a></h2>
102
103    
104
105    <table class="related"><tr><th>Related Modules</th><th>Related Directives</th></tr><tr><td><ul><li><code class="module"><a href="/mod/mod_dir.html">mod_dir</a></code></li><li><code class="module"><a href="/mod/mpm_common.html">mpm_common</a></code></li><li><code class="module"><a href="/mod/mod_status.html">mod_status</a></code></li></ul></td><td><ul><li><code class="directive"><a href="/mod/core.html#allowoverride">AllowOverride</a></code></li><li><code class="directive"><a href="/mod/mod_dir.html#directoryindex">DirectoryIndex</a></code></li><li><code class="directive"><a href="/mod/core.html#hostnamelookups">HostnameLookups</a></code></li><li><code class="directive"><a href="/mod/core.html#enablemmap">EnableMMAP</a></code></li><li><code class="directive"><a href="/mod/core.html#enablesendfile">EnableSendfile</a></code></li><li><code class="directive"><a href="/mod/core.html#keepalivetimeout">KeepAliveTimeout</a></code></li><li><code class="directive"><a href="/mod/prefork.html#maxspareservers">MaxSpareServers</a></code></li><li><code class="directive"><a href="/mod/prefork.html#minspareservers">MinSpareServers</a></code></li><li><code class="directive"><a href="/mod/core.html#options">Options</a></code></li><li><code class="directive"><a href="/mod/mpm_common.html#startservers">StartServers</a></code></li></ul></td></tr></table>
106
107    <h3><a name="dns" id="dns">HostnameLookups and other DNS considerations</a></h3>
108
109      
110
111      <p>Prior to Apache 1.3, <code class="directive"><a href="/mod/core.html#hostnamelookups">HostnameLookups</a></code> defaulted to <code>On</code>.
112      This adds latency to every request because it requires a
113      DNS lookup to complete before the request is finished. In
114      Apache 1.3 this setting defaults to <code>Off</code>. If you need
115      to have addresses in your log files resolved to hostnames, use the
116      <code class="program"><a href="/programs/logresolve.html">logresolve</a></code>
117      program that comes with Apache, or one of the numerous log
118      reporting packages which are available.</p>
119
120      <p>It is recommended that you do this sort of postprocessing of
121      your log files on some machine other than the production web
122      server machine, in order that this activity not adversely affect
123      server performance.</p>
124
125      <p>If you use any <code><code class="directive"><a href="/mod/mod_authz_host.html#allow">Allow</a></code> from domain</code> or <code><code class="directive"><a href="/mod/mod_authz_host.html#deny">Deny</a></code> from domain</code>
126      directives (i.e., using a hostname, or a domain name, rather than
127      an IP address) then you will pay for
128      two DNS lookups (a reverse, followed by a forward lookup
129      to make sure that the reverse is not being spoofed). For best
130      performance, therefore, use IP addresses, rather than names, when
131      using these directives, if possible.</p>
132
133      <p>Note that it's possible to scope the directives, such as
134      within a <code>&lt;Location /server-status&gt;</code> section.
135      In this case the DNS lookups are only performed on requests
136      matching the criteria. Here's an example which disables lookups
137      except for <code>.html</code> and <code>.cgi</code> files:</p>
138
139      <div class="example"><p><code>
140        HostnameLookups off<br />
141        &lt;Files ~ "\.(html|cgi)$"&gt;<br />
142        <span class="indent">
143          HostnameLookups on<br />
144        </span>
145        &lt;/Files&gt;
146      </code></p></div>
147
148      <p>But even still, if you just need DNS names in some CGIs you
149      could consider doing the <code>gethostbyname</code> call in the
150      specific CGIs that need it.</p>
151
152    
153
154    <h3><a name="symlinks" id="symlinks">FollowSymLinks and SymLinksIfOwnerMatch</a></h3>
155
156      
157
158      <p>Wherever in your URL-space you do not have an <code>Options
159      FollowSymLinks</code>, or you do have an <code>Options
160      SymLinksIfOwnerMatch</code> Apache will have to issue extra
161      system calls to check up on symlinks. One extra call per
162      filename component. For example, if you had:</p>
163
164      <div class="example"><p><code>
165        DocumentRoot /www/htdocs<br />
166        &lt;Directory /&gt;<br />
167        <span class="indent">
168          Options SymLinksIfOwnerMatch<br />
169        </span>
170        &lt;/Directory&gt;
171      </code></p></div>
172
173      <p>and a request is made for the URI <code>/index.html</code>.
174      Then Apache will perform <code>lstat(2)</code> on
175      <code>/www</code>, <code>/www/htdocs</code>, and
176      <code>/www/htdocs/index.html</code>. The results of these
177      <code>lstats</code> are never cached, so they will occur on
178      every single request. If you really desire the symlinks
179      security checking you can do something like this:</p>
180
181      <div class="example"><p><code>
182        DocumentRoot /www/htdocs<br />
183        &lt;Directory /&gt;<br />
184        <span class="indent">
185          Options FollowSymLinks<br />
186        </span>
187        &lt;/Directory&gt;<br />
188        <br />
189        &lt;Directory /www/htdocs&gt;<br />
190        <span class="indent">
191          Options -FollowSymLinks +SymLinksIfOwnerMatch<br />
192        </span>
193        &lt;/Directory&gt;
194      </code></p></div>
195
196      <p>This at least avoids the extra checks for the
197      <code class="directive"><a href="/mod/core.html#documentroot">DocumentRoot</a></code> path.
198      Note that you'll need to add similar sections if you
199      have any <code class="directive"><a href="/mod/mod_alias.html#alias">Alias</a></code> or
200      <code class="directive"><a href="/mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> paths
201      outside of your document root. For highest performance,
202      and no symlink protection, set <code>FollowSymLinks</code>
203      everywhere, and never set <code>SymLinksIfOwnerMatch</code>.</p>
204
205    
206
207    <h3><a name="htaccess" id="htaccess">AllowOverride</a></h3>
208
209      
210
211      <p>Wherever in your URL-space you allow overrides (typically
212      <code>.htaccess</code> files) Apache will attempt to open
213      <code>.htaccess</code> for each filename component. For
214      example,</p>
215
216      <div class="example"><p><code>
217        DocumentRoot /www/htdocs<br />
218        &lt;Directory /&gt;<br />
219        <span class="indent">
220          AllowOverride all<br />
221        </span>
222        &lt;/Directory&gt;
223      </code></p></div>
224
225      <p>and a request is made for the URI <code>/index.html</code>.
226      Then Apache will attempt to open <code>/.htaccess</code>,
227      <code>/www/.htaccess</code>, and
228      <code>/www/htdocs/.htaccess</code>. The solutions are similar
229      to the previous case of <code>Options FollowSymLinks</code>.
230      For highest performance use <code>AllowOverride None</code>
231      everywhere in your filesystem.</p>
232
233    
234
235    <h3><a name="negotiation" id="negotiation">Negotiation</a></h3>
236
237      
238
239      <p>If at all possible, avoid content-negotiation if you're
240      really interested in every last ounce of performance. In
241      practice the benefits of negotiation outweigh the performance
242      penalties. There's one case where you can speed up the server.
243      Instead of using a wildcard such as:</p>
244
245      <div class="example"><p><code>
246        DirectoryIndex index
247      </code></p></div>
248
249      <p>Use a complete list of options:</p>
250
251      <div class="example"><p><code>
252        DirectoryIndex index.cgi index.pl index.shtml index.html
253      </code></p></div>
254
255      <p>where you list the most common choice first.</p>
256
257      <p>Also note that explicitly creating a <code>type-map</code>
258      file provides better performance than using
259      <code>MultiViews</code>, as the necessary information can be
260      determined by reading this single file, rather than having to
261      scan the directory for files.</p>
262
263    <p>If your site needs content negotiation consider using
264    <code>type-map</code> files, rather than the <code>Options
265    MultiViews</code> directive to accomplish the negotiation. See the
266    <a href="/content-negotiation.html">Content Negotiation</a>
267    documentation for a full discussion of the methods of negotiation,
268    and instructions for creating <code>type-map</code> files.</p>
269
270    
271
272    <h3>Memory-mapping</h3>
273
274      
275
276      <p>In situations where Apache 2.x needs to look at the contents
277      of a file being delivered--for example, when doing server-side-include
278      processing--it normally memory-maps the file if the OS supports
279      some form of <code>mmap(2)</code>.</p>
280
281      <p>On some platforms, this memory-mapping improves performance.
282      However, there are cases where memory-mapping can hurt the performance
283      or even the stability of the httpd:</p>
284
285      <ul>
286        <li>
287          <p>On some operating systems, <code>mmap</code> does not scale
288          as well as <code>read(2)</code> when the number of CPUs increases.
289          On multiprocessor Solaris servers, for example, Apache 2.x sometimes
290          delivers server-parsed files faster when <code>mmap</code> is disabled.</p>
291        </li>
292
293        <li>
294          <p>If you memory-map a file located on an NFS-mounted filesystem
295          and a process on another NFS client machine deletes or truncates
296          the file, your process may get a bus error the next time it tries
297          to access the mapped file content.</p>
298        </li>
299      </ul>
300
301      <p>For installations where either of these factors applies, you
302      should use <code>EnableMMAP off</code> to disable the memory-mapping
303      of delivered files. (Note: This directive can be overridden on
304      a per-directory basis.)</p>
305
306    
307
308    <h3>Sendfile</h3>
309
310      
311
312      <p>In situations where Apache 2.x can ignore the contents of the file
313      to be delivered -- for example, when serving static file content --
314      it normally uses the kernel sendfile support the file if the OS
315      supports the <code>sendfile(2)</code> operation.</p>
316
317      <p>On most platforms, using sendfile improves performance by eliminating
318      separate read and send mechanics.  However, there are cases where using
319      sendfile can harm the stability of the httpd:</p>
320
321      <ul>
322        <li>
323          <p>Some platforms may have broken sendfile support that the build
324          system did not detect, especially if the binaries were built on
325          another box and moved to such a machine with broken sendfile support.</p>
326        </li>
327        <li>
328          <p>With an NFS-mounted files, the kernel may be unable
329          to reliably serve the network file through it's own cache.</p>
330        </li>
331      </ul>
332
333      <p>For installations where either of these factors applies, you
334      should use <code>EnableSendfile off</code> to disable sendfile
335      delivery of file contents. (Note: This directive can be overridden
336      on a per-directory basis.)</p>
337
338    
339
340    <h3><a name="process" id="process">Process Creation</a></h3>
341
342      
343
344      <p>Prior to Apache 1.3 the <code class="directive"><a href="/mod/prefork.html#minspareservers">MinSpareServers</a></code>, <code class="directive"><a href="/mod/prefork.html#maxspareservers">MaxSpareServers</a></code>, and <code class="directive"><a href="/mod/mpm_common.html#startservers">StartServers</a></code> settings all had drastic effects on
345      benchmark results. In particular, Apache required a "ramp-up"
346      period in order to reach a number of children sufficient to serve
347      the load being applied. After the initial spawning of
348      <code class="directive"><a href="/mod/mpm_common.html#startservers">StartServers</a></code> children,
349      only one child per second would be created to satisfy the
350      <code class="directive"><a href="/mod/prefork.html#minspareservers">MinSpareServers</a></code>
351      setting. So a server being accessed by 100 simultaneous
352      clients, using the default <code class="directive"><a href="/mod/mpm_common.html#startservers">StartServers</a></code> of <code>5</code> would take on
353      the order 95 seconds to spawn enough children to handle
354      the load. This works fine in practice on real-life servers,
355      because they aren't restarted frequently. But does really
356      poorly on benchmarks which might only run for ten minutes.</p>
357
358      <p>The one-per-second rule was implemented in an effort to
359      avoid swamping the machine with the startup of new children. If
360      the machine is busy spawning children it can't service
361      requests. But it has such a drastic effect on the perceived
362      performance of Apache that it had to be replaced. As of Apache
363      1.3, the code will relax the one-per-second rule. It will spawn
364      one, wait a second, then spawn two, wait a second, then spawn
365      four, and it will continue exponentially until it is spawning
366      32 children per second. It will stop whenever it satisfies the
367      <code class="directive"><a href="/mod/prefork.html#minspareservers">MinSpareServers</a></code>
368      setting.</p>
369
370      <p>This appears to be responsive enough that it's almost
371      unnecessary to twiddle the <code class="directive"><a href="/mod/prefork.html#minspareservers">MinSpareServers</a></code>, <code class="directive"><a href="/mod/prefork.html#maxspareservers">MaxSpareServers</a></code> and <code class="directive"><a href="/mod/mpm_common.html#startservers">StartServers</a></code> knobs. When more than 4 children are
372      spawned per second, a message will be emitted to the
373      <code class="directive"><a href="/mod/core.html#errorlog">ErrorLog</a></code>. If you
374      see a lot of these errors then consider tuning these settings.
375      Use the <code class="module"><a href="/mod/mod_status.html">mod_status</a></code> output as a guide.</p>
376
377    <p>Related to process creation is process death induced by the
378    <code class="directive"><a href="/mod/mpm_common.html#maxrequestsperchild">MaxRequestsPerChild</a></code>
379    setting. By default this is <code>0</code>,
380    which means that there is no limit to the number of requests
381    handled per child. If your configuration currently has this set
382    to some very low number, such as <code>30</code>, you may want to bump this
383    up significantly. If you are running SunOS or an old version of
384    Solaris, limit this to <code>10000</code> or so because of memory leaks.</p>
385
386    <p>When keep-alives are in use, children will be kept busy
387    doing nothing waiting for more requests on the already open
388    connection. The default <code class="directive"><a href="/mod/core.html#keepalivetimeout">KeepAliveTimeout</a></code> of <code>5</code>
389    seconds attempts to minimize this effect. The tradeoff here is
390    between network bandwidth and server resources. In no event
391    should you raise this above about <code>60</code> seconds, as <a href="http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-4.html">
392    most of the benefits are lost</a>.</p>
393
394    
395
396  </div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
397<div class="section">
398<h2><a name="compiletime" id="compiletime">Compile-Time Configuration Issues</a></h2>
399
400    
401
402    <h3>Choosing an MPM</h3>
403
404      
405
406      <p>Apache 2.x supports pluggable concurrency models, called
407      <a href="/mpm.html">Multi-Processing Modules</a> (MPMs).
408      When building Apache, you must choose an MPM to use.  There
409      are platform-specific MPMs for some platforms:
410      <code class="module"><a href="/mod/beos.html">beos</a></code>, <code class="module"><a href="/mod/mpm_netware.html">mpm_netware</a></code>,
411      <code class="module"><a href="/mod/mpmt_os2.html">mpmt_os2</a></code>, and <code class="module"><a href="/mod/mpm_winnt.html">mpm_winnt</a></code>.  For
412      general Unix-type systems, there are several MPMs from which
413      to choose.  The choice of MPM can affect the speed and scalability
414      of the httpd:</p>
415
416      <ul>
417
418        <li>The <code class="module"><a href="/mod/worker.html">worker</a></code> MPM uses multiple child
419        processes with many threads each.  Each thread handles
420        one connection at a time.  Worker generally is a good
421        choice for high-traffic servers because it has a smaller
422        memory footprint than the prefork MPM.</li>
423
424        <li>The <code class="module"><a href="/mod/prefork.html">prefork</a></code> MPM uses multiple child
425        processes with one thread each.  Each process handles
426        one connection at a time.  On many systems, prefork is
427        comparable in speed to worker, but it uses more memory.
428        Prefork's threadless design has advantages over worker
429        in some situations: it can be used with non-thread-safe
430        third-party modules, and it is easier to debug on platforms
431        with poor thread debugging support.</li>
432
433      </ul>
434
435      <p>For more information on these and other MPMs, please
436      see the MPM <a href="/mpm.html">documentation</a>.</p>
437
438    
439
440    <h3><a name="modules" id="modules">Modules</a></h3>
441
442        
443
444        <p>Since memory usage is such an important consideration in
445        performance, you should attempt to eliminate modules that you are
446        not actually using. If you have built the modules as <a href="/dso.html">DSOs</a>, eliminating modules is a simple
447        matter of commenting out the associated <code class="directive"><a href="/mod/mod_so.html#loadmodule">LoadModule</a></code> directive for that module.
448        This allows you to experiment with removing modules, and seeing
449        if your site still functions in their absense.</p>
450
451        <p>If, on the other hand, you have modules statically linked
452        into your Apache binary, you will need to recompile Apache in
453        order to remove unwanted modules.</p>
454
455        <p>An associated question that arises here is, of course, what
456        modules you need, and which ones you don't. The answer here
457        will, of course, vary from one web site to another. However, the
458        <em>minimal</em> list of modules which you can get by with tends
459        to include <code class="module"><a href="/mod/mod_mime.html">mod_mime</a></code>, <code class="module"><a href="/mod/mod_dir.html">mod_dir</a></code>,
460        and <code class="module"><a href="/mod/mod_log_config.html">mod_log_config</a></code>. <code>mod_log_config</code> is,
461        of course, optional, as you can run a web site without log
462        files. This is, however, not recommended.</p>
463
464    
465
466    <h3>Atomic Operations</h3>
467
468      
469
470      <p>Some modules, such as <code class="module"><a href="/mod/mod_cache.html">mod_cache</a></code> and
471      recent development builds of the worker MPM, use APR's
472      atomic API.  This API provides atomic operations that can
473      be used for lightweight thread synchronization.</p>
474
475      <p>By default, APR implements these operations using the
476      most efficient mechanism available on each target
477      OS/CPU platform.  Many modern CPUs, for example, have
478      an instruction that does an atomic compare-and-swap (CAS)
479      operation in hardware.  On some platforms, however, APR
480      defaults to a slower, mutex-based implementation of the
481      atomic API in order to ensure compatibility with older
482      CPU models that lack such instructions.  If you are
483      building Apache for one of these platforms, and you plan
484      to run only on newer CPUs, you can select a faster atomic
485      implementation at build time by configuring Apache with
486      the <code>--enable-nonportable-atomics</code> option:</p>
487
488      <div class="example"><p><code>
489        /buildconf<br />
490        /configure --with-mpm=worker --enable-nonportable-atomics=yes
491      </code></p></div>
492
493      <p>The <code>--enable-nonportable-atomics</code> option is
494      relevant for the following platforms:</p>
495
496      <ul>
497
498        <li>Solaris on SPARC<br />
499            By default, APR uses mutex-based atomics on Solaris/SPARC.
500            If you configure with <code>--enable-nonportable-atomics</code>,
501            however, APR generates code that uses a SPARC v8plus opcode for
502            fast hardware compare-and-swap.  If you configure Apache with
503            this option, the atomic operations will be more efficient
504            (allowing for lower CPU utilization and higher concurrency),
505            but the resulting executable will run only on UltraSPARC
506            chips.
507        </li>
508
509        <li>Linux on x86<br />
510            By default, APR uses mutex-based atomics on Linux.  If you
511            configure with <code>--enable-nonportable-atomics</code>,
512            however, APR generates code that uses a 486 opcode for fast
513            hardware compare-and-swap.  This will result in more efficient
514            atomic operations, but the resulting executable will run only
515            on 486 and later chips (and not on 386).
516        </li>
517
518      </ul>
519
520    
521
522    <h3>mod_status and ExtendedStatus On</h3>
523
524      
525
526      <p>If you include <code class="module"><a href="/mod/mod_status.html">mod_status</a></code> and you also set
527      <code>ExtendedStatus On</code> when building and running
528      Apache, then on every request Apache will perform two calls to
529      <code>gettimeofday(2)</code> (or <code>times(2)</code>
530      depending on your operating system), and (pre-1.3) several
531      extra calls to <code>time(2)</code>. This is all done so that
532      the status report contains timing indications. For highest
533      performance, set <code>ExtendedStatus off</code> (which is the
534      default).</p>
535
536    
537
538    <h3>accept Serialization - multiple sockets</h3>
539
540      
541
542    <div class="warning"><h3>Warning:</h3>
543      <p>This section has not been fully updated
544      to take into account changes made in the 2.x version of the
545      Apache HTTP Server. Some of the information may still be
546      relevant, but please use it with care.</p>
547    </div>
548
549      <p>This discusses a shortcoming in the Unix socket API. Suppose
550      your web server uses multiple <code class="directive"><a href="/mod/mpm_common.html#listen">Listen</a></code> statements to listen on either multiple
551      ports or multiple addresses. In order to test each socket
552      to see if a connection is ready Apache uses
553      <code>select(2)</code>. <code>select(2)</code> indicates that a
554      socket has <em>zero</em> or <em>at least one</em> connection
555      waiting on it. Apache's model includes multiple children, and
556      all the idle ones test for new connections at the same time. A
557      naive implementation looks something like this (these examples
558      do not match the code, they're contrived for pedagogical
559      purposes):</p>
560
561      <div class="example"><p><code>
562        for (;;) {<br />
563        <span class="indent">
564          for (;;) {<br />
565          <span class="indent">
566            fd_set accept_fds;<br />
567            <br />
568            FD_ZERO (&amp;accept_fds);<br />
569            for (i = first_socket; i &lt;= last_socket; ++i) {<br />
570            <span class="indent">
571              FD_SET (i, &amp;accept_fds);<br />
572            </span>
573            }<br />
574            rc = select (last_socket+1, &amp;accept_fds, NULL, NULL, NULL);<br />
575            if (rc &lt; 1) continue;<br />
576            new_connection = -1;<br />
577            for (i = first_socket; i &lt;= last_socket; ++i) {<br />
578            <span class="indent">
579              if (FD_ISSET (i, &amp;accept_fds)) {<br />
580              <span class="indent">
581                new_connection = accept (i, NULL, NULL);<br />
582                if (new_connection != -1) break;<br />
583              </span>
584              }<br />
585            </span>
586            }<br />
587            if (new_connection != -1) break;<br />
588          </span>
589          }<br />
590          process the new_connection;<br />
591        </span>
592        }
593      </code></p></div>
594
595      <p>But this naive implementation has a serious starvation problem.
596      Recall that multiple children execute this loop at the same
597      time, and so multiple children will block at
598      <code>select</code> when they are in between requests. All
599      those blocked children will awaken and return from
600      <code>select</code> when a single request appears on any socket
601      (the number of children which awaken varies depending on the
602      operating system and timing issues). They will all then fall
603      down into the loop and try to <code>accept</code> the
604      connection. But only one will succeed (assuming there's still
605      only one connection ready), the rest will be <em>blocked</em>
606      in <code>accept</code>. This effectively locks those children
607      into serving requests from that one socket and no other
608      sockets, and they'll be stuck there until enough new requests
609      appear on that socket to wake them all up. This starvation
610      problem was first documented in <a href="http://bugs.apache.org/index/full/467">PR#467</a>. There
611      are at least two solutions.</p>
612
613      <p>One solution is to make the sockets non-blocking. In this
614      case the <code>accept</code> won't block the children, and they
615      will be allowed to continue immediately. But this wastes CPU
616      time. Suppose you have ten idle children in
617      <code>select</code>, and one connection arrives. Then nine of
618      those children will wake up, try to <code>accept</code> the
619      connection, fail, and loop back into <code>select</code>,
620      accomplishing nothing. Meanwhile none of those children are
621      servicing requests that occurred on other sockets until they
622      get back up to the <code>select</code> again. Overall this
623      solution does not seem very fruitful unless you have as many
624      idle CPUs (in a multiprocessor box) as you have idle children,
625      not a very likely situation.</p>
626
627      <p>Another solution, the one used by Apache, is to serialize
628      entry into the inner loop. The loop looks like this
629      (differences highlighted):</p>
630
631      <div class="example"><p><code>
632        for (;;) {<br />
633        <span class="indent">
634          <strong>accept_mutex_on ();</strong><br />
635          for (;;) {<br />
636          <span class="indent">
637            fd_set accept_fds;<br />
638            <br />
639            FD_ZERO (&amp;accept_fds);<br />
640            for (i = first_socket; i &lt;= last_socket; ++i) {<br />
641            <span class="indent">
642              FD_SET (i, &amp;accept_fds);<br />
643            </span>
644            }<br />
645            rc = select (last_socket+1, &amp;accept_fds, NULL, NULL, NULL);<br />
646            if (rc &lt; 1) continue;<br />
647            new_connection = -1;<br />
648            for (i = first_socket; i &lt;= last_socket; ++i) {<br />
649            <span class="indent">
650              if (FD_ISSET (i, &amp;accept_fds)) {<br />
651              <span class="indent">
652                new_connection = accept (i, NULL, NULL);<br />
653                if (new_connection != -1) break;<br />
654              </span>
655              }<br />
656            </span>
657            }<br />
658            if (new_connection != -1) break;<br />
659          </span>
660          }<br />
661          <strong>accept_mutex_off ();</strong><br />
662          process the new_connection;<br />
663        </span>
664        }
665      </code></p></div>
666
667      <p><a id="serialize" name="serialize">The functions</a>
668      <code>accept_mutex_on</code> and <code>accept_mutex_off</code>
669      implement a mutual exclusion semaphore. Only one child can have
670      the mutex at any time. There are several choices for
671      implementing these mutexes. The choice is defined in
672      <code>src/conf.h</code> (pre-1.3) or
673      <code>src/include/ap_config.h</code> (1.3 or later). Some
674      architectures do not have any locking choice made, on these
675      architectures it is unsafe to use multiple
676      <code class="directive"><a href="/mod/mpm_common.html#listen">Listen</a></code>
677      directives.</p>
678
679      <p>The directive <code class="directive"><a href="/mod/mpm_common.html#acceptmutex">AcceptMutex</a></code> can be used to
680      change the selected mutex implementation at run-time.</p>
681
682      <dl>
683        <dt><code>AcceptMutex flock</code></dt>
684
685        <dd>
686          <p>This method uses the <code>flock(2)</code> system call to
687          lock a lock file (located by the <code class="directive"><a href="/mod/mpm_common.html#lockfile">LockFile</a></code> directive).</p>
688        </dd>
689
690        <dt><code>AcceptMutex fcntl</code></dt>
691
692        <dd>
693          <p>This method uses the <code>fcntl(2)</code> system call to
694          lock a lock file (located by the <code class="directive"><a href="/mod/mpm_common.html#lockfile">LockFile</a></code> directive).</p>
695        </dd>
696
697        <dt><code>AcceptMutex sysvsem</code></dt>
698
699        <dd>
700          <p>(1.3 or later) This method uses SysV-style semaphores to
701          implement the mutex. Unfortunately SysV-style semaphores have
702          some bad side-effects. One is that it's possible Apache will
703          die without cleaning up the semaphore (see the
704          <code>ipcs(8)</code> man page). The other is that the
705          semaphore API allows for a denial of service attack by any
706          CGIs running under the same uid as the webserver
707          (<em>i.e.</em>, all CGIs, unless you use something like
708          <code class="program"><a href="/programs/suexec.html">suexec</a></code> or <code>cgiwrapper</code>). For these
709          reasons this method is not used on any architecture except
710          IRIX (where the previous two are prohibitively expensive
711          on most IRIX boxes).</p>
712        </dd>
713
714        <dt><code>AcceptMutex pthread</code></dt>
715
716        <dd>
717          <p>(1.3 or later) This method uses POSIX mutexes and should
718          work on any architecture implementing the full POSIX threads
719          specification, however appears to only work on Solaris (2.5
720          or later), and even then only in certain configurations. If
721          you experiment with this you should watch out for your server
722          hanging and not responding. Static content only servers may
723          work just fine.</p>
724        </dd>
725
726        <dt><code>AcceptMutex posixsem</code></dt>
727
728        <dd>
729          <p>(2.0 or later)  This method uses POSIX semaphores.  The
730          semaphore ownership is not recovered if a thread in the process
731          holding the mutex segfaults, resulting in a hang of the web
732          server.</p>
733        </dd>
734
735      </dl>
736
737      <p>If your system has another method of serialization which
738      isn't in the above list then it may be worthwhile adding code
739      for it to APR.</p>
740
741      <p>Another solution that has been considered but never
742      implemented is to partially serialize the loop -- that is, let
743      in a certain number of processes. This would only be of
744      interest on multiprocessor boxes where it's possible multiple
745      children could run simultaneously, and the serialization
746      actually doesn't take advantage of the full bandwidth. This is
747      a possible area of future investigation, but priority remains
748      low because highly parallel web servers are not the norm.</p>
749
750      <p>Ideally you should run servers without multiple
751      <code class="directive"><a href="/mod/mpm_common.html#listen">Listen</a></code>
752      statements if you want the highest performance.
753      But read on.</p>
754
755    
756
757    <h3>accept Serialization - single socket</h3>
758
759      
760
761      <p>The above is fine and dandy for multiple socket servers, but
762      what about single socket servers? In theory they shouldn't
763      experience any of these same problems because all children can
764      just block in <code>accept(2)</code> until a connection
765      arrives, and no starvation results. In practice this hides
766      almost the same "spinning" behaviour discussed above in the
767      non-blocking solution. The way that most TCP stacks are
768      implemented, the kernel actually wakes up all processes blocked
769      in <code>accept</code> when a single connection arrives. One of
770      those processes gets the connection and returns to user-space,
771      the rest spin in the kernel and go back to sleep when they
772      discover there's no connection for them. This spinning is
773      hidden from the user-land code, but it's there nonetheless.
774      This can result in the same load-spiking wasteful behaviour
775      that a non-blocking solution to the multiple sockets case
776      can.</p>
777
778      <p>For this reason we have found that many architectures behave
779      more "nicely" if we serialize even the single socket case. So
780      this is actually the default in almost all cases. Crude
781      experiments under Linux (2.0.30 on a dual Pentium pro 166
782      w/128Mb RAM) have shown that the serialization of the single
783      socket case causes less than a 3% decrease in requests per
784      second over unserialized single-socket. But unserialized
785      single-socket showed an extra 100ms latency on each request.
786      This latency is probably a wash on long haul lines, and only an
787      issue on LANs. If you want to override the single socket
788      serialization you can define
789      <code>SINGLE_LISTEN_UNSERIALIZED_ACCEPT</code> and then
790      single-socket servers will not serialize at all.</p>
791
792    
793
794    <h3>Lingering Close</h3>
795
796      
797
798      <p>As discussed in <a href="http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-connection-00.txt">
799      draft-ietf-http-connection-00.txt</a> section 8, in order for
800      an HTTP server to <strong>reliably</strong> implement the
801      protocol it needs to shutdown each direction of the
802      communication independently (recall that a TCP connection is
803      bi-directional, each half is independent of the other). This
804      fact is often overlooked by other servers, but is correctly
805      implemented in Apache as of 1.2.</p>
806
807      <p>When this feature was added to Apache it caused a flurry of
808      problems on various versions of Unix because of a
809      shortsightedness. The TCP specification does not state that the
810      <code>FIN_WAIT_2</code> state has a timeout, but it doesn't prohibit it.
811      On systems without the timeout, Apache 1.2 induces many sockets
812      stuck forever in the <code>FIN_WAIT_2</code> state. In many cases this
813      can be avoided by simply upgrading to the latest TCP/IP patches
814      supplied by the vendor. In cases where the vendor has never
815      released patches (<em>i.e.</em>, SunOS4 -- although folks with
816      a source license can patch it themselves) we have decided to
817      disable this feature.</p>
818
819      <p>There are two ways of accomplishing this. One is the socket
820      option <code>SO_LINGER</code>. But as fate would have it, this
821      has never been implemented properly in most TCP/IP stacks. Even
822      on those stacks with a proper implementation (<em>i.e.</em>,
823      Linux 2.0.31) this method proves to be more expensive (cputime)
824      than the next solution.</p>
825
826      <p>For the most part, Apache implements this in a function
827      called <code>lingering_close</code> (in
828      <code>http_main.c</code>). The function looks roughly like
829      this:</p>
830
831      <div class="example"><p><code>
832        void lingering_close (int s)<br />
833        {<br />
834        <span class="indent">
835          char junk_buffer[2048];<br />
836          <br />
837          /* shutdown the sending side */<br />
838          shutdown (s, 1);<br />
839          <br />
840          signal (SIGALRM, lingering_death);<br />
841          alarm (30);<br />
842          <br />
843          for (;;) {<br />
844          <span class="indent">
845            select (s for reading, 2 second timeout);<br />
846            if (error) break;<br />
847            if (s is ready for reading) {<br />
848            <span class="indent">
849              if (read (s, junk_buffer, sizeof (junk_buffer)) &lt;= 0) {<br />
850              <span class="indent">
851                break;<br />
852              </span>
853              }<br />
854              /* just toss away whatever is here */<br />
855            </span>
856            }<br />
857          </span>
858          }<br />
859          <br />
860          close (s);<br />
861        </span>
862        }
863      </code></p></div>
864
865      <p>This naturally adds some expense at the end of a connection,
866      but it is required for a reliable implementation. As HTTP/1.1
867      becomes more prevalent, and all connections are persistent,
868      this expense will be amortized over more requests. If you want
869      to play with fire and disable this feature you can define
870      <code>NO_LINGCLOSE</code>, but this is not recommended at all.
871      In particular, as HTTP/1.1 pipelined persistent connections
872      come into use <code>lingering_close</code> is an absolute
873      necessity (and <a href="http://www.w3.org/Protocols/HTTP/Performance/Pipeline.html">
874      pipelined connections are faster</a>, so you want to support
875      them).</p>
876
877    
878
879    <h3>Scoreboard File</h3>
880
881      
882
883      <p>Apache's parent and children communicate with each other
884      through something called the scoreboard. Ideally this should be
885      implemented in shared memory. For those operating systems that
886      we either have access to, or have been given detailed ports
887      for, it typically is implemented using shared memory. The rest
888      default to using an on-disk file. The on-disk file is not only
889      slow, but it is unreliable (and less featured). Peruse the
890      <code>src/main/conf.h</code> file for your architecture and
891      look for either <code>USE_MMAP_SCOREBOARD</code> or
892      <code>USE_SHMGET_SCOREBOARD</code>. Defining one of those two
893      (as well as their companions <code>HAVE_MMAP</code> and
894      <code>HAVE_SHMGET</code> respectively) enables the supplied
895      shared memory code. If your system has another type of shared
896      memory, edit the file <code>src/main/http_main.c</code> and add
897      the hooks necessary to use it in Apache. (Send us back a patch
898      too please.)</p>
899
900      <div class="note">Historical note: The Linux port of Apache didn't start to
901      use shared memory until version 1.2 of Apache. This oversight
902      resulted in really poor and unreliable behaviour of earlier
903      versions of Apache on Linux.</div>
904
905    
906
907    <h3>DYNAMIC_MODULE_LIMIT</h3>
908
909      
910
911      <p>If you have no intention of using dynamically loaded modules
912      (you probably don't if you're reading this and tuning your
913      server for every last ounce of performance) then you should add
914      <code>-DDYNAMIC_MODULE_LIMIT=0</code> when building your
915      server. This will save RAM that's allocated only for supporting
916      dynamically loaded modules.</p>
917
918    
919
920  </div><div class="top"><a href="#page-header"><img alt="top" src="/images/up.gif" /></a></div>
921<div class="section">
922<h2><a name="trace" id="trace">Appendix: Detailed Analysis of a Trace</a></h2>
923
924    
925
926    <p>Here is a system call trace of Apache 2.0.38 with the worker MPM
927    on Solaris 8. This trace was collected using:</p>
928
929    <div class="example"><p><code>
930      truss -l -p <var>httpd_child_pid</var>.
931    </code></p></div>
932
933    <p>The <code>-l</code> option tells truss to log the ID of the
934    LWP (lightweight process--Solaris's form of kernel-level thread)
935    that invokes each system call.</p>
936
937    <p>Other systems may have different system call tracing utilities
938    such as <code>strace</code>, <code>ktrace</code>, or <code>par</code>.
939    They all produce similar output.</p>
940
941    <p>In this trace, a client has requested a 10KB static file
942    from the httpd. Traces of non-static requests or requests
943    with content negotiation look wildly different (and quite ugly
944    in some cases).</p>
945
946    <div class="example"><pre>/67:    accept(3, 0x00200BEC, 0x00200C0C, 1) (sleeping...)
947/67:    accept(3, 0x00200BEC, 0x00200C0C, 1)            = 9</pre></div>
948
949    <p>In this trace, the listener thread is running within LWP #67.</p>
950
951    <div class="note">Note the lack of <code>accept(2)</code> serialization. On this
952    particular platform, the worker MPM uses an unserialized accept by
953    default unless it is listening on multiple ports.</div>
954
955    <div class="example"><pre>/65:    lwp_park(0x00000000, 0)                         = 0
956/67:    lwp_unpark(65, 1)                               = 0</pre></div>
957
958    <p>Upon accepting the connection, the listener thread wakes up
959    a worker thread to do the request processing. In this trace,
960    the worker thread that handles the request is mapped to LWP #65.</p>
961
962    <div class="example"><pre>/65:    getsockname(9, 0x00200BA4, 0x00200BC4, 1)       = 0</pre></div>
963
964    <p>In order to implement virtual hosts, Apache needs to know
965    the local socket address used to accept the connection. It
966    is possible to eliminate this call in many situations (such
967    as when there are no virtual hosts, or when
968    <code class="directive"><a href="/mod/mpm_common.html#listen">Listen</a></code> directives
969    are used which do not have wildcard addresses). But
970    no effort has yet been made to do these optimizations. </p>
971
972    <div class="example"><pre>/65:    brk(0x002170E8)                                 = 0
973/65:    brk(0x002190E8)                                 = 0</pre></div>
974
975    <p>The <code>brk(2)</code> calls allocate memory from the heap.
976    It is rare to see these in a system call trace, because the httpd
977    uses custom memory allocators (<code>apr_pool</code> and
978    <code>apr_bucket_alloc</code>) for most request processing.
979    In this trace, the httpd has just been started, so it must
980    call <code>malloc(3)</code> to get the blocks of raw memory
981    with which to create the custom memory allocators.</p>
982
983    <div class="example"><pre>/65:    fcntl(9, F_GETFL, 0x00000000)                   = 2
984/65:    fstat64(9, 0xFAF7B818)                          = 0
985/65:    getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B910, 2190656) = 0
986/65:    fstat64(9, 0xFAF7B818)                          = 0
987/65:    getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B914, 2190656) = 0
988/65:    setsockopt(9, 65535, 8192, 0xFAF7B918, 4, 2190656) = 0
989/65:    fcntl(9, F_SETFL, 0x00000082)                   = 0</pre></div>
990
991    <p>Next, the worker thread puts the connection to the client (file
992    descriptor 9) in non-blocking mode. The <code>setsockopt(2)</code>
993    and <code>getsockopt(2)</code> calls are a side-effect of how
994    Solaris's libc handles <code>fcntl(2)</code> on sockets.</p>
995
996    <div class="example"><pre>/65:    read(9, " G E T   / 1 0 k . h t m".., 8000)     = 97</pre></div>
997
998    <p>The worker thread reads the request from the client.</p>
999
1000    <div class="example"><pre>/65:    stat("/var/httpd/apache/httpd-8999/htdocs/10k.html", 0xFAF7B978) = 0
1001/65:    open("/var/httpd/apache/httpd-8999/htdocs/10k.html", O_RDONLY) = 10</pre></div>
1002
1003    <p>This httpd has been configured with <code>Options FollowSymLinks</code>
1004    and <code>AllowOverride None</code>.  Thus it doesn't need to
1005    <code>lstat(2)</code> each directory in the path leading up to the
1006    requested file, nor check for <code>.htaccess</code> files.
1007    It simply calls <code>stat(2)</code> to verify that the file:
1008    1) exists, and 2) is a regular file, not a directory.</p>
1009
1010    <div class="example"><pre>/65:    sendfilev(0, 9, 0x00200F90, 2, 0xFAF7B53C)      = 10269</pre></div>
1011
1012    <p>In this example, the httpd is able to send the HTTP response
1013    header and the requested file with a single <code>sendfilev(2)</code>
1014    system call. Sendfile semantics vary among operating systems. On some other
1015    systems, it is necessary to do a <code>write(2)</code> or
1016    <code>writev(2)</code> call to send the headers before calling
1017    <code>sendfile(2)</code>.</p>
1018
1019    <div class="example"><pre>/65:    write(4, " 1 2 7 . 0 . 0 . 1   -  ".., 78)      = 78</pre></div>
1020
1021    <p>This <code>write(2)</code> call records the request in the
1022    access log. Note that one thing missing from this trace is a
1023    <code>time(2)</code> call. Unlike Apache 1.3, Apache 2.x uses
1024    <code>gettimeofday(3)</code> to look up the time. On some operating
1025    systems, like Linux or Solaris, <code>gettimeofday</code> has an
1026    optimized implementation that doesn't require as much overhead
1027    as a typical system call.</p>
1028
1029    <div class="example"><pre>/65:    shutdown(9, 1, 1)                               = 0
1030/65:    poll(0xFAF7B980, 1, 2000)                       = 1
1031/65:    read(9, 0xFAF7BC20, 512)                        = 0
1032/65:    close(9)                                        = 0</pre></div>
1033
1034    <p>The worker thread does a lingering close of the connection.</p>
1035
1036    <div class="example"><pre>/65:    close(10)                                       = 0
1037/65:    lwp_park(0x00000000, 0)         (sleeping...)</pre></div>
1038
1039    <p>Finally the worker thread closes the file that it has just delivered
1040    and blocks until the listener assigns it another connection.</p>
1041
1042    <div class="example"><pre>/67:    accept(3, 0x001FEB74, 0x001FEB94, 1) (sleeping...)</pre></div>
1043
1044    <p>Meanwhile, the listener thread is able to accept another connection
1045    as soon as it has dispatched this connection to a worker thread (subject
1046    to some flow-control logic in the worker MPM that throttles the listener
1047    if all the available workers are busy).  Though it isn't apparent from
1048    this trace, the next <code>accept(2)</code> can (and usually does, under
1049    high load conditions) occur in parallel with the worker thread's handling
1050    of the just-accepted connection.</p>
1051
1052  </div></div>
1053<div class="bottomlang">
1054<p><span>Available Languages: </span><a href="/en/misc/perf-tuning.html" title="English">&nbsp;en&nbsp;</a> |
1055<a href="/ko/misc/perf-tuning.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a> |
1056<a href="/tr/misc/perf-tuning.html" hreflang="tr" rel="alternate" title="T�rk�e">&nbsp;tr&nbsp;</a></p>
1057</div><div class="top"><a href="#page-header"><img src="/images/up.gif" alt="top" /></a></div><div class="section"><h2><a id="comments_section" name="comments_section">Comments</a></h2><div class="warning"><strong>Notice:</strong><br />This is not a Q&amp;A section. Comments placed here should be pointed towards suggestions on improving the documentation or server, and may be removed again by our moderators if they are either implemented or considered invalid/off-topic. Questions on how to manage the Apache HTTP Server should be directed at either our IRC channel, #httpd, on Freenode, or sent to our <a href="http://httpd.apache.org/lists.html">mailing lists</a>.</div>
1058<script type="text/javascript"><!--//--><![CDATA[//><!--
1059var comments_shortname = 'httpd';
1060var comments_identifier = 'http://httpd.apache.org/docs/2.2/misc/perf-tuning.html';
1061(function(w, d) {
1062    if (w.location.hostname.toLowerCase() == "httpd.apache.org") {
1063        d.write('<div id="comments_thread"><\/div>');
1064        var s = d.createElement('script');
1065        s.type = 'text/javascript';
1066        s.async = true;
1067        s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
1068        (d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
1069    }
1070    else { 
1071        d.write('<div id="comments_thread">Comments are disabled for this page at the moment.<\/div>');
1072    }
1073})(window, document);
1074//--><!]]></script></div><div id="footer">
1075<p class="apache">Copyright 2013 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
1076<p class="menu"><a href="/mod/">Modules</a> | <a href="/mod/directives.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="/glossary.html">Glossary</a> | <a href="/sitemap.html">Sitemap</a></p></div><script type="text/javascript"><!--//--><![CDATA[//><!--
1077if (typeof(prettyPrint) !== 'undefined') {
1078    prettyPrint();
1079}
1080//--><!]]></script>
1081</body></html>