xref: /lighttpd1.4/doc/outdated/performance.txt (revision d958cf32)
1==================
2Performance Tuning
3==================
4
5[[ Note: latest version is found at https://wiki.lighttpd.net/Docs_Performance ]]
6[[ Note: see version with links at https://wiki.lighttpd.net/Docs_Performance ]]
7
8important performance tuning rules
9
10* Prefer lighttpd defaults unless you have a reason to change a setting,
11  and unless you test that changing the setting is beneficial to you.
12* Proper functionality is more important than marginal increases in performance;
13  a web server that does not function as intended is not useful.
14  Do not sacrifice security or desired operational functioning for marginal
15  performance improvements.
16* Performance tuning is not magic. The recommended approach is that one change
17  be made at a time, that the change be tested and benchmarked, and that if the
18  change does not have a measurable and positive impact in real-world scenarios,
19  that the change be reverted.
20
21lighttpd is generally pretty snappy.
22Most of the following are micro-optimizations.
23No changes are required unless you have a specific performance issue that you
24must address.
25
26
27lighttpd configuration performance tuning (technical guidelines)
28-----------------------------------------
29
30* less is more (and is often simpler, too)
31  - rely on defaults where possible to reduce unnecessary (duplicative) config
32    processing (at runtime) to process configuration directives which were
33    already set to the default values
34  - set config options in the global scope rather than repeating in sub-scopes.
35    lighttpd optimizes configuration settings in the global scope and makes
36    those settings the defaults
37  - TLS configuration can be set in the global scope and inherited by multiple
38    $SERVER["socket"]
39      ssl.pemfile = "..."
40      ssl.privkey = "..."
41      $SERVER["socket"] == ":443" { ssl.engine = "enable" }
42      $SERVER["socket"] == "[::]:443" { ssl.engine = "enable" }
43  - list only the modules actually used and enabled in server.modules;
44    comment out the others
45    - each loaded module registers itself into lighttpd hooks and gets a chance
46      to handle each request, which is is unnecessary if a module is loaded but
47      not otherwise configured to be used
48    - server.compat-module-load = "disable" skips loading the default modules
49      (mod_indexfile, mod_dirlisting, mod_staticfile), and you can then
50      explicitly add one or more to server.modules to use them
51  - tweaks to remove optional functionality
52    - server.tag = "" skips sending "Server: lighttpd/1.4.xx" in responses;
53      alternatively, use: server.tag = "lighttpd" to hide the lighttpd version
54    - server.range-requests = "disable" can be used if all server responses are
55      small files, but otherwise it is recommended to be left enabled
56  - review the default lighttpd config provided by your distro
57    - configs provided by distros aim to be newbie friendly but can introduce
58      complexity of yet another config framework
59    - configs provided by distros are often out-dated and then kept for historic
60      compatibility, rather than current best practices
61    - example: ~20 years ago some widely used versions of Adobe Acrobat reader
62      plugin PDF clients misbehaved with range requests.  Unfortunately, the
63      config setting to disable range requests for PDFs has been cargo-culted
64      into configs since then.  Prefer to comment out or remove:
65        $HTTP["url"] =~ "\.pdf$" { server.range-requests = "disable" }
66  - server.max-connections limits the maximum number of simultaneous connections
67    to handle and also affects memory usage for the connection cache
68    - default is (about) 1365 which is oversized for all but the largest
69      systems. Embedded systems might set server.max-connections = 16 or lower
70  - server.max-worker = 0 should generally be left unset (or "0"), as
71    CPU bottlenecks are usually elsewhere
72  - server.follow-symlink = "enable" (default) should be left enabled.  If such
73    restrictions are required, prefer to run a separate lighttp instance under a
74    separate user account, and enforce more restrictive file access permissions.
75  - ssl.read-ahead = "disable" (default) is strongly recommended for slower,
76    embedded systems which process TLS packets more slowly than network
77    wire-speed.  For faster systems, test if ssl.read-ahead = "enable" improves
78    performance (or not)
79  - prefer to configure mod_extforward extforward.hap-PROXY for lighttpd
80    instances behind HAProxy or load balancers supporting the HAProxy PROXY
81    protocol
82* minimize conditional processing (but not at the cost of proper functionality)
83  - more conditions means more config processing at runtime
84  - more conditions means more memory used by config per request
85  - avoid repeating conditions and its opposite by joining them into if/else
86      <condition> { ... } else { ... }
87      <condition> { ... } else <condition> { ... } else { ... }
88  - sometimes it may take fewer config lines to set a config option once in the
89    global scope and then, where necessary, to unset the option in a small
90    number of conditions rather than leaving the default in the global scope
91    and enabling the config option in many more conditions
92  - having no config conditions will be among the fastest configs to be
93    processed, but config processing at runtime is fast and is not typically
94    a bottleneck
95* dynamic backends (mod_proxy, mod_fastcgi, mod_scgi, mod_ajp13, ...)
96  - prefer to use unix domain sockets (instead of TCP sockets) for connections
97    from lighttpd to backends running on the same host
98  - lighttpd can listen on a unix domain socket
99      (server.bind = "/path/to/lighttpd.sock")
100    and lighttpd mod_proxy can act as a reverse-proxy to a backend lighttpd
101    server.  Use with mod_extforward to preserve client remote address for the
102    backend.
103* mod_fastcgi
104  - Recommended: use PHP-FPM (FastCGI Process Manager),
105    which is available as a package in many OS distros
106  - If not using PHP-FPM, then see Docs_PerformanceFastCGI
107    - lighttpd provides mechanisms for lighttpd to start up PHP backends, and
108      that works well, but PHP-FPM is the modern and recommended mechanism to
109      manage PHP backends
110* mod_rewrite and mod_redirect: short-circuiting
111  (when using a sequence of regexes)
112  - consider putting static file matches (passed through unmodified) first,
113    and using a blank target to indicate no modification
114  - consider using a blank match as a catch-all, rather than "^(.*)",
115    which will still match all, but without the regex
116      url.rewrite-once = (
117        "^/static/|\.(?:css|jpg)$" => "",
118        "" => "/index.php${url.path}${qsa}"
119      )
120* mod_indexfile: reduce the number of entries in index-file.names,
121  if mod_indexfile is enabled
122  - index-file.names = ("index.html") as a list of one or two entries rather
123    than a list of, say, 10 differenent file extensions
124* cache tuning
125  - stat_cache: default server.stat_cache-engine = "simple" works well for
126    typical usage and caches stat() results for 1-2 seconds.  Test with
127    server.stat-cache-engine = "inotify" or server.stat-cache-engine = "kqueue"
128    for stat() results to be cached longer (16 seconds)
129  - mod_auth: set auth.cache = ("max-age" => "600") to cache passwords (default
130    disabled), but acknowledge changes to your security posture if enabling the
131    cache. (since lighttpd 1.4.56)
132  - mod_deflate: set deflate.cache-dir to cache (and reuse) compressed static
133    assets based on ETag (since lighttpd 1.4.56)
134  - mod_dirlisting: set dir-listing.cache = ( ... ) to configure caching of
135    generated directory listings (since lighttpd 1.4.60)
136* do not sacrifice security to save a few CPU cycles
137  - server.http-parseopts* option defaults are recommended, and are very fast
138  - disabling server.http-parseopts* might save a few CPU cycles, but is an
139    anti-pattern for secure configurations
140  - server.http-parseopts* options should be modified only when the
141    functionality needs to be tuned for proper site operation
142  - ETag response headers are used in HTTP/1.1 conditional caching.
143    ETag response headers are also required for mod_deflate and strongly
144    recommended with mod_webdav.  While lighttpd ETag generation for
145    static content can be disabled for micro-benchmarking purposes,
146    ETag generation (default enabled) is recommended for production use
147    (etag.use-inode, etag.use-mtime, etag.use-size)
148* compile lighttpd with mmap support (./configure --enable-mmap) to improve
149  mod_deflate performance
150
151
152lighttpd configuration for use of operating system (OS) features
153----------------------------------------------------------------
154
155lighttpd generally chooses optimal defaults for the OS on which it is running.
156Prefer lighttpd defaults unless something is not functioning correctly.
157(Please report bugs and include your platform information if the lighttpd OS
158 defaults are not working correctly.)
159
160* server.event-handler (e.g. epoll, kqueue, event ports, devpoll, poll, ...)
161* server.network-backend (e.g. sendfile, writev, write)
162
163
164lighttpd configuration tuning for high-traffic sites with a large number of connections
165---------------------------------------------------------------------------------------
166
167* test with server.max-fds = 16384 (or higher) and OS system and/or per-user
168  ulimit -Hn might need to be adjusted to allow this or higher values.
169  For each 4k increase in server.max-fds, lighttpd uses an additional ~100 kb
170  of memory for internal structures, not including memory used by each active
171  connection.  (In other words, there is a marginal cost for using very high
172  values when there are not nearly so many simultaneous open connections).
173  server.max-connections is calculated to be 1/3 of server.max-fds if
174  server.max-connections is not configured.
175
176
177lighttpd configuration tuning for low-memory systems
178----------------------------------------------------
179
180* test with server.max-fds = 128 (or lower)
181* test with server.max-connections = 16 (or lower)
182* test with server.listen-backlog = 16 (or lower)
183* (default) server.stat_cache-engine = "simple"
184* (default) ssl.read-ahead = "disable"
185* support for the HTTP/2 protocol (enabled by default in lighttpd 1.4.59) uses
186  more memory than HTTP/1.1; low-memory systems might choose to disable HTTP/2
187  protocol support: server.feature-flags += ("server.h2proto" => "disable")
188
189
190lighttpd configuration tuning for traffic shapping (download rate-limiting)
191--------------------------------------------------
192
193connection.kbytes-per-second
194server.kbytes-per-second
195
196
197lighttpd configuration tuning for timeouts
198------------------------------------------
199
200To free up connections more quickly, tune down the idle timeouts for how long
201lighttpd waits to read or write to the client (when lighttpd is trying to read
202or write), or how long lighttpd waits for the next keep-alive request, and for
203how many keep-alive requests, before lighttpd closes the connection.  A value
204of 0 disables an idle timeout and is not recommended.
205* server.max-read-idle = 60
206* server.max-write-idle = 360
207* server.max-keep-alive-idle = 5
208* server.max-keep-alive-requests = 100
209Generally, server.max-keep-alive-requests should not be set to 0 since setting
210up a new TCP connection takes more resources than keeping an open idle fd,
211especially if the connection is over TLS.
212
213
214Platform-Specific Notes
215=======================
216
217Note: The following is old and possibly out-dated.
218      Please consider only as a starting point for further testing.
219
220Linux
221-----
222
223For Linux 2.4.x you should think about compiling lighttpd with the option
224``--disable-lfs`` to disable the support for files larger than 2GB. lighttpd will
225fall back to the ``writev() + mmap()`` network calls which is ok, but not as
226fast as possible but support files larger than 2GB.
227
228Disabling the TCP options reduces the overhead of each TCP packet and might
229help to get the last few percent of performance out of the server. Be aware that
230disabling these options most likely decreases performance for high-latency and lossy
231links.
232
233- net.ipv4.tcp_sack = 0
234- net.ipv4.tcp_timestamps = 0
235
236Increasing the TCP send and receive buffers will increase the performance a
237lot if (and only if) you have a lot of large files to send.
238
239- net.ipv4.tcp_wmem = 4096 65536 524288
240- net.core.wmem_max = 1048576
241
242If you have a lot of large file uploads, increasing the receive buffers will help.
243
244- net.ipv4.tcp_rmem = 4096 87380 524288
245- net.core.rmem_max = 1048576
246
247Keep in mind that every TCP connection uses the configured amount of memory for socket
248buffers. If you've got many connections this can quickly drain the available memory.
249
250See http://www.acc.umu.se/~maswan/linux-netperf.txt for more information on these parameters.
251
252FreeBSD
253-------
254
255On FreeBSD you might gain some performance by enabling accept filters. Just
256compile your kernel with: ::
257
258  options   ACCEPT_FILTER_HTTP
259
260For more ideas about tuning FreeBSD read: tuning(7)
261
262Reducing the recvspace should always be ok if the server only handles HTTP
263requests without large uploads. Increasing the sendspace would reduce the
264system load if you have a lot of large files to be sent, but keep in mind that
265you have to provide the memory in the kernel for each connection. 1024 * 64KB
266would mean 64MB of kernel RAM. Keep this in mind.
267
268- net.inet.tcp.recvspace = 4096
269
270