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="<-" alt="<-" src="/images/left.gif" /></a></div> 21<div id="path"> 22<a href="http://www.apache.org/">Apache</a> > <a href="http://httpd.apache.org/">HTTP Server</a> > <a href="http://httpd.apache.org/docs/">Documentation</a> > <a href="../">Version 2.2</a> > <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"> en </a> | 25<a href="/ko/misc/perf-tuning.html" hreflang="ko" rel="alternate" title="Korean"> ko </a> | 26<a href="/tr/misc/perf-tuning.html" hreflang="tr" rel="alternate" title="T�rk�e"> tr </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><Location /server-status></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 <Files ~ "\.(html|cgi)$"><br /> 142 <span class="indent"> 143 HostnameLookups on<br /> 144 </span> 145 </Files> 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 <Directory /><br /> 167 <span class="indent"> 168 Options SymLinksIfOwnerMatch<br /> 169 </span> 170 </Directory> 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 <Directory /><br /> 184 <span class="indent"> 185 Options FollowSymLinks<br /> 186 </span> 187 </Directory><br /> 188 <br /> 189 <Directory /www/htdocs><br /> 190 <span class="indent"> 191 Options -FollowSymLinks +SymLinksIfOwnerMatch<br /> 192 </span> 193 </Directory> 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 <Directory /><br /> 219 <span class="indent"> 220 AllowOverride all<br /> 221 </span> 222 </Directory> 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 (&accept_fds);<br /> 569 for (i = first_socket; i <= last_socket; ++i) {<br /> 570 <span class="indent"> 571 FD_SET (i, &accept_fds);<br /> 572 </span> 573 }<br /> 574 rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);<br /> 575 if (rc < 1) continue;<br /> 576 new_connection = -1;<br /> 577 for (i = first_socket; i <= last_socket; ++i) {<br /> 578 <span class="indent"> 579 if (FD_ISSET (i, &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 (&accept_fds);<br /> 640 for (i = first_socket; i <= last_socket; ++i) {<br /> 641 <span class="indent"> 642 FD_SET (i, &accept_fds);<br /> 643 </span> 644 }<br /> 645 rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);<br /> 646 if (rc < 1) continue;<br /> 647 new_connection = -1;<br /> 648 for (i = first_socket; i <= last_socket; ++i) {<br /> 649 <span class="indent"> 650 if (FD_ISSET (i, &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)) <= 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"> en </a> | 1055<a href="/ko/misc/perf-tuning.html" hreflang="ko" rel="alternate" title="Korean"> ko </a> | 1056<a href="/tr/misc/perf-tuning.html" hreflang="tr" rel="alternate" title="T�rk�e"> tr </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&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>