227 lines
6.8 KiB

Performance Improvements
Module: core
:Author: Jan Kneschke
:Date: $Date: 2004/11/03 22:26:05 $
:Revision: $Revision: 1.3 $
handling performance issues in lighttpd
.. meta::
:keywords: lighttpd, performance
.. contents:: Table of Contents
Performance Issues
lighttpd is optimized into various directions. The most important is
performance. The operation system has two major facalities to help lighttpd
a deliver it best performance.
HTTP Keep-Alive
Disabling keep-alive might help your server if you suffer from a large
number of open file-descriptors.
The defaults fo the server is: ::
server.max-keep-alive-requests = 128
server.max-keep-alive-idle = 30
server.max-read-idle = 60
server.max-write-idle = 360
handling 128 keep-alive requests in a row on a single connection, waiting 30 seconds
before a unused keep-alive connection get dropped by lighttpd.
If you handle several connections at once under a high load (let's assume 500 connections
in parallel for 24h) you might run into the out-of-fd problem described below. ::
server.max-keep-alive-requests = 4
server.max-keep-alive-idle = 4
would release the connections earlier and would free file-descriptors without a to large
performance loss.
Disabling keep-alive completly is the last choice if you are still short in filedescriptors: ::
server.max-keep-alive-requests = 0
Event Handlers
The first one is the Event Handler which cares about notifying the server
that one of the connections is ready to send or to recieve. As you can see
every OS has at least the select() call which has some limitations.
============ ========== ===============
OS Method Config-Value
============ ========== ===============
all select select
Unix poll poll
Linux 2.4+ rt-signals linux-rtsig
Linux 2.6+ epoll linux-sysepoll
Solaris /dev/poll solaris-devpoll
FreeBSD, ... kqueue freebsd-kqueue
============ ========== ===============
For more infomation in this topic take a look at
The event-handler can be set by specifying the 'Config-Value' from above
in the ``server.event-handler`` variable
e.g.: ::
server.event-handler = "linux-sysepoll"
Network Handlers
The basic network interface for all platforms at the syscalls read() and
write(). Each modern OS provides its own syscall to help network servers
to transfer files as fast as possible.
If you want to send out a file from the webserver it does make any sense
to copy the file into the webserver just to write() it back into a socket
in the next step.
sendfile() minimizes the work in the application and pushes a file directly
into the network card (idealy spoken).
lighttpd supports all major platform specific calls:
========== ==========
OS Method
========== ==========
all write
Unix writev
Linux 2.4+ sendfile
Linux 2.6+ sendfile64
Solaris sendfilev
FreeBSD sendfile
========== ==========
They are selected automaticly on compile-time. If you have problems check
./src/network_backend.h and disable the corresponding USE\_... define.
Max Connections
As lighttpd is a single-threaded server its main resource limit is the
number of file-descriptors which is (on most systems) set to 1024 by default.
If you are running a high-traffic site you might want to increase this limit
by setting ::
server.max-fds = 2048
This only works if lighttpd is started as root.
Out-of-fd condition
As fds are used for tcp/ip sockets, files, directories, ... a simple request
for a PHP page might result in using 3 fds:
1. the TCP/IP socket to the client
2. the TCP/IP and Unix domain socket to the FastCGI process
3. the filehandle to the file in the document-root to check if it is really existing
If lighttpd runs out of file-descriptors it will stop accepting new
connections for while to use the currently available fds (file-descriptors)
to handle the currently running requests.
If more than 90% of the fds are used the the handling of new connections is
disabled, if it dropes below 80% again new connection will accepted again.
Under some circumstances you will see ::
... accept() failed: Too many open files
in the error-log. This tells you the you had to many new requests at once
and lighttpd could not disable the incomming connections soon enough. The
connection is drop and the client will get a error-message like 'connection
failed'. This is very rare and might only occur in test-setups.
Increasing the ``server.max-fds`` limit will reduce the propability of this
stat() cache
A stat(2) can be expensive, caching it saves time adn context-switches..
Instead of stat() for the existence of the file you can stat() it once and
monitor the directory the file is in for modifications. As long as the
directiry doesn't change, the files in it are all the same.
With the help of FAM or gamin you can use kernel events to assure that
your stat-cache is up to date. ::
server.stat-cache-engine = "fam" # either fam, simple or off
Plattform Specific Notes
For Linux 2.4.x should 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.
- 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 large files to send.
- net.ipv4.tcp_wmem = 4096 65536 524288
- net.core.wmem_max = 1048576
If you have a lot 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 the buffers have to multiplied by server.max-fds and be
allocated in the Kernel area. Be carefull with that.
On FreeBSD you might gain some performance by enabling accept-filters. Just
compile your kernel with: ::
For more ideas in 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 large files to be sent, but keep in mind that
you to provide the memory in kernel for each connection. 1024 * 64k would mean
64M of kernel-ram. Keep this in mind.
- net.inet.tcp.recvspace = 4096