123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- ==================
- Performance Tuning
- ==================
- [[ Note: latest version is found at https://wiki.lighttpd.net/Docs_Performance ]]
- [[ Note: see version with links at https://wiki.lighttpd.net/Docs_Performance ]]
- important performance tuning rules
- * Prefer lighttpd defaults unless you have a reason to change a setting,
- and unless you test that changing the setting is beneficial to you.
- * Proper functionality is more important than marginal increases in performance;
- a web server that does not function as intended is not useful.
- Do not sacrifice security or desired operational functioning for marginal
- performance improvements.
- * Performance tuning is not magic. The recommended approach is that one change
- be made at a time, that the change be tested and benchmarked, and that if the
- change does not have a measurable and positive impact in real-world scenarios,
- that the change be reverted.
- lighttpd is generally pretty snappy.
- Most of the following are micro-optimizations.
- No changes are required unless you have a specific performance issue that you
- must address.
- lighttpd configuration performance tuning (technical guidelines)
- -----------------------------------------
- * less is more (and is often simpler, too)
- - rely on defaults where possible to reduce unnecessary (duplicative) config
- processing (at runtime) to process configuration directives which were
- already set to the default values
- - set config options in the global scope rather than repeating in sub-scopes.
- lighttpd optimizes configuration settings in the global scope and makes
- those settings the defaults
- - TLS configuration can be set in the global scope and inherited by multiple
- $SERVER["socket"]
- ssl.pemfile = "..."
- ssl.privkey = "..."
- $SERVER["socket"] == ":443" { ssl.engine = "enable" }
- $SERVER["socket"] == "[::]:443" { ssl.engine = "enable" }
- - list only the modules actually used and enabled in server.modules;
- comment out the others
- - each loaded module registers itself into lighttpd hooks and gets a chance
- to handle each request, which is is unnecessary if a module is loaded but
- not otherwise configured to be used
- - server.compat-module-load = "disable" skips loading the default modules
- (mod_indexfile, mod_dirlisting, mod_staticfile), and you can then
- explicitly add one or more to server.modules to use them
- - tweaks to remove optional functionality
- - server.tag = "" skips sending "Server: lighttpd/1.4.xx" in responses;
- alternatively, use: server.tag = "lighttpd" to hide the lighttpd version
- - server.range-requests = "disable" can be used if all server responses are
- small files, but otherwise it is recommended to be left enabled
- - review the default lighttpd config provided by your distro
- - configs provided by distros aim to be newbie friendly but can introduce
- complexity of yet another config framework
- - configs provided by distros are often out-dated and then kept for historic
- compatibility, rather than current best practices
- - example: ~20 years ago some widely used versions of Adobe Acrobat reader
- plugin PDF clients misbehaved with range requests. Unfortunately, the
- config setting to disable range requests for PDFs has been cargo-culted
- into configs since then. Prefer to comment out or remove:
- $HTTP["url"] =~ "\.pdf$" { server.range-requests = "disable" }
- - server.max-connections limits the maximum number of simultaneous connections
- to handle and also affects memory usage for the connection cache
- - default is (about) 1365 which is oversized for all but the largest
- systems. Embedded systems might set server.max-connections = 16 or lower
- - server.max-worker = 0 should generally be left unset (or "0"), as
- CPU bottlenecks are usually elsewhere
- - server.follow-symlink = "enable" (default) should be left enabled. If such
- restrictions are required, prefer to run a separate lighttp instance under a
- separate user account, and enforce more restrictive file access permissions.
- - ssl.read-ahead = "disable" (default) is strongly recommended for slower,
- embedded systems which process TLS packets more slowly than network
- wire-speed. For faster systems, test if ssl.read-ahead = "enable" improves
- performance (or not)
- - prefer to configure mod_extforward extforward.hap-PROXY for lighttpd
- instances behind HAProxy or load balancers supporting the HAProxy PROXY
- protocol
- * minimize conditional processing (but not at the cost of proper functionality)
- - more conditions means more config processing at runtime
- - more conditions means more memory used by config per request
- - avoid repeating conditions and its opposite by joining them into if/else
- <condition> { ... } else { ... }
- <condition> { ... } else <condition> { ... } else { ... }
- - sometimes it may take fewer config lines to set a config option once in the
- global scope and then, where necessary, to unset the option in a small
- number of conditions rather than leaving the default in the global scope
- and enabling the config option in many more conditions
- - having no config conditions will be among the fastest configs to be
- processed, but config processing at runtime is fast and is not typically
- a bottleneck
- * dynamic backends (mod_proxy, mod_fastcgi, mod_scgi, mod_ajp13, ...)
- - prefer to use unix domain sockets (instead of TCP sockets) for connections
- from lighttpd to backends running on the same host
- - lighttpd can listen on a unix domain socket
- (server.bind = "/path/to/lighttpd.sock")
- and lighttpd mod_proxy can act as a reverse-proxy to a backend lighttpd
- server. Use with mod_extforward to preserve client remote address for the
- backend.
- * mod_fastcgi
- - Recommended: use PHP-FPM (FastCGI Process Manager),
- which is available as a package in many OS distros
- - If not using PHP-FPM, then see Docs_PerformanceFastCGI
- - lighttpd provides mechanisms for lighttpd to start up PHP backends, and
- that works well, but PHP-FPM is the modern and recommended mechanism to
- manage PHP backends
- * mod_rewrite and mod_redirect: short-circuiting
- (when using a sequence of regexes)
- - consider putting static file matches (passed through unmodified) first,
- and using a blank target to indicate no modification
- - consider using a blank match as a catch-all, rather than "^(.*)",
- which will still match all, but without the regex
- url.rewrite-once = (
- "^/static/|\.(?:css|jpg)$" => "",
- "" => "/index.php${url.path}${qsa}"
- )
- * mod_indexfile: reduce the number of entries in index-file.names,
- if mod_indexfile is enabled
- - index-file.names = ("index.html") as a list of one or two entries rather
- than a list of, say, 10 differenent file extensions
- * cache tuning
- - stat_cache: default server.stat_cache-engine = "simple" works well for
- typical usage and caches stat() results for 1-2 seconds. Test with
- server.stat-cache-engine = "inotify" or server.stat-cache-engine = "kqueue"
- for stat() results to be cached longer (16 seconds)
- - mod_auth: set auth.cache = ("max-age" => "600") to cache passwords (default
- disabled), but acknowledge changes to your security posture if enabling the
- cache. (since lighttpd 1.4.56)
- - mod_deflate: set deflate.cache-dir to cache (and reuse) compressed static
- assets based on ETag (since lighttpd 1.4.56)
- - mod_dirlisting: set dir-listing.cache = ( ... ) to configure caching of
- generated directory listings (since lighttpd 1.4.60)
- * do not sacrifice security to save a few CPU cycles
- - server.http-parseopts* option defaults are recommended, and are very fast
- - disabling server.http-parseopts* might save a few CPU cycles, but is an
- anti-pattern for secure configurations
- - server.http-parseopts* options should be modified only when the
- functionality needs to be tuned for proper site operation
- - ETag response headers are used in HTTP/1.1 conditional caching.
- ETag response headers are also required for mod_deflate and strongly
- recommended with mod_webdav. While lighttpd ETag generation for
- static content can be disabled for micro-benchmarking purposes,
- ETag generation (default enabled) is recommended for production use
- (etag.use-inode, etag.use-mtime, etag.use-size)
- * compile lighttpd with mmap support (./configure --enable-mmap) to improve
- mod_deflate performance
- lighttpd configuration for use of operating system (OS) features
- ----------------------------------------------------------------
- lighttpd generally chooses optimal defaults for the OS on which it is running.
- Prefer lighttpd defaults unless something is not functioning correctly.
- (Please report bugs and include your platform information if the lighttpd OS
- defaults are not working correctly.)
- * server.event-handler (e.g. epoll, kqueue, event ports, devpoll, poll, ...)
- * server.network-backend (e.g. sendfile, writev, write)
- lighttpd configuration tuning for high-traffic sites with a large number of connections
- ---------------------------------------------------------------------------------------
- * test with server.max-fds = 16384 (or higher) and OS system and/or per-user
- ulimit -Hn might need to be adjusted to allow this or higher values.
- For each 4k increase in server.max-fds, lighttpd uses an additional ~100 kb
- of memory for internal structures, not including memory used by each active
- connection. (In other words, there is a marginal cost for using very high
- values when there are not nearly so many simultaneous open connections).
- server.max-connections is calculated to be 1/3 of server.max-fds if
- server.max-connections is not configured.
- lighttpd configuration tuning for low-memory systems
- ----------------------------------------------------
- * test with server.max-fds = 128 (or lower)
- * test with server.max-connections = 16 (or lower)
- * test with server.listen-backlog = 16 (or lower)
- * (default) server.stat_cache-engine = "simple"
- * (default) ssl.read-ahead = "disable"
- * support for the HTTP/2 protocol (enabled by default in lighttpd 1.4.59) uses
- more memory than HTTP/1.1; low-memory systems might choose to disable HTTP/2
- protocol support: server.feature-flags += ("server.h2proto" => "disable")
- lighttpd configuration tuning for traffic shapping (download rate-limiting)
- --------------------------------------------------
- connection.kbytes-per-second
- server.kbytes-per-second
- lighttpd configuration tuning for timeouts
- ------------------------------------------
- To free up connections more quickly, tune down the idle timeouts for how long
- lighttpd waits to read or write to the client (when lighttpd is trying to read
- or write), or how long lighttpd waits for the next keep-alive request, and for
- how many keep-alive requests, before lighttpd closes the connection. A value
- of 0 disables an idle timeout and is not recommended.
- * server.max-read-idle = 60
- * server.max-write-idle = 360
- * server.max-keep-alive-idle = 5
- * server.max-keep-alive-requests = 100
- Generally, server.max-keep-alive-requests should not be set to 0 since setting
- up a new TCP connection takes more resources than keeping an open idle fd,
- especially if the connection is over TLS.
- Platform-Specific Notes
- =======================
- Note: The following is old and possibly out-dated.
- Please consider only as a starting point for further testing.
- Linux
- -----
- For Linux 2.4.x you should think about compiling lighttpd with the option
- ``--disable-lfs`` to disable the support for files larger than 2GB. lighttpd will
- fall back to the ``writev() + mmap()`` network calls which is ok, but not as
- fast as possible but support files larger than 2GB.
- Disabling the TCP options reduces the overhead of each TCP packet and might
- help to get the last few percent of performance out of the server. Be aware that
- disabling these options most likely decreases performance for high-latency and lossy
- links.
- - net.ipv4.tcp_sack = 0
- - net.ipv4.tcp_timestamps = 0
- Increasing the TCP send and receive buffers will increase the performance a
- lot if (and only if) you have a lot of large files to send.
- - net.ipv4.tcp_wmem = 4096 65536 524288
- - net.core.wmem_max = 1048576
- If you have a lot of large file uploads, increasing the receive buffers will help.
- - net.ipv4.tcp_rmem = 4096 87380 524288
- - net.core.rmem_max = 1048576
- Keep in mind that every TCP connection uses the configured amount of memory for socket
- buffers. If you've got many connections this can quickly drain the available memory.
- See http://www.acc.umu.se/~maswan/linux-netperf.txt for more information on these parameters.
- FreeBSD
- -------
- On FreeBSD you might gain some performance by enabling accept filters. Just
- compile your kernel with: ::
- options ACCEPT_FILTER_HTTP
- For more ideas about tuning FreeBSD read: tuning(7)
- Reducing the recvspace should always be ok if the server only handles HTTP
- requests without large uploads. Increasing the sendspace would reduce the
- system load if you have a lot of large files to be sent, but keep in mind that
- you have to provide the memory in the kernel for each connection. 1024 * 64KB
- would mean 64MB of kernel RAM. Keep this in mind.
- - net.inet.tcp.recvspace = 4096
|