Lighttz - a simple and fast web server
Update : A naive implementation of using Lua 5.1 to generate a dynamic response has been added. This loads Lua, loads a Lua script and executes it. Retrieves the string response and returns it to the browser. Take a look below for a new additional download link.
Cheers
There are many well written , fast web servers around with full features for CGI , FastCGI , proxying and dynamic language support such as Ruby, PHP and Python. So what is Lighttz ? It's a small HTTP server written in C , benchmarked against the big guns. It is by no means a replacement for the big four, and is mainly a testing showcase. For the sake of brevity, the comparison of the first benchmarks will compare the following web servers:
- Apache/2.2.8-mpm-prefork
- lighttpd/1.4.19
- nginx/0.5.33
- userver-0.6.0 - compiled and run with epoll support
- lighttz/0.1 - libev epoll event model
Short summary and the configuration as tested is below. Please note that other event models such as select and poll are available under each server , but these were picked for the performance or wide use ( in case of Apache ) .
Apache - http://httpd.apache.org/
The usual pre-forking server most, widely used to power many websites.
Lighttpd - http://www.lighttpd.net/
Also a very popular server. Instead of a forking model, it utilizes a fast a very well performing epoll mechanism.
Nginx - http://sysoev.ru/en/
A little younger but equally fast server , which also utilizes epoll event model.
Userver - http://userver.uwaterloo.ca/index.php
A small, microwebserver that's mostly used for tests and benchmarks. Project is maintained at University of Waterloo.
Lighttz -
A short C program that simulates an HTTP server and handles the requests using Libev and epoll.
Test platform
Ubuntu 8.04 , Kernel 2.6.24-16 SMP , 2GB RAM, Core2Duo 2.4GHz
Benchmarking Client Program
ApacheBench . Command used:
ab -c1000 -n1000000 <host:port> . The test document index.html is a 357 byte static file. Lighttz did not use the static file, it sent out the exact same contents as index.html contained in a char array.
The above simulated 1000 concurrent clients making 1000000 requests .
Results
Each result is an average of three runs with one pre-warming run to let each server utilize the cache.
Requests per second. Listed in order of fastest to slowest.
- Lighttz - 14,719 ( Cpu usage: 40-50% , Memory: 188 KB , 1 process )
- Lighttpd - 14,701 ( Cpu usage: 65-85%, Memory: 6.6 MB , 1 process )
- Nginx - 14,378 (Cpu usage: 65-80%, Memory: 2.1 MB , 2 processes )
- Userver - 13,221 ( Cpu usage: 75-90%, Memory: 1.2 MB, 1 process )
- Apache - 9,512 ( Cpu Usage: 60-80%, Memory: 3.5 MB x 147 processes , 514 MB total )
Hardware used, other running servers and operating systems will reflect different results. The tests were not run to define maximum performance for all solutions. Each application will apply a different level of stress on the server.
Source code for Lighttz : http://zenebo.com/lighttz.c.tar.gz
Lua version: http://zenebo.com/lighttz_lua.tar.gz
Libev : http://software.schmorp.de/pkg/libev.html
Index.html file was taken from SuperJared.com article located here: http://superjared.com/entry/benching-lighttpd-vs-nginx-static-files/

Posted on October 14th, 2008 at 8:48 am
Could you help me compiling lighttz.c?
gcc -o”lighttz” ./lighttz.o -lev
returns an error
/usr/bin/ld: can’t found -lev
collect2: ld returned 1 exit status
Posted on October 14th, 2008 at 9:49 am
Joshua, that is a linker error.
1. You have to install libev . Download the latest source code for LibEv , do a makefile compile and install .
The linker should then find the compiled libev in your lib folder. Depending on the system , it may be located in : /usr/local/lib
The compiled .so shared object will be found when given the -lev flag at compile time .
If you encounter errors with dynamic linking, you can set a search path to the directory where your libev resides. Let’s say that it is in /usr/local/lib . You could tell the linker to search that directory by typing this in command line:
LD_RUN_PATH=/usr/local/lib
export LD_RUN_PATH
Arek Bochinski
Posted on February 7th, 2009 at 8:13 am
gcc -LLIBDIR -o lighttz lighttz.c -lev
I should use “-LLIBDIR” flag, else:
[cocobear@cocobear Download]$ ./lighttz
./lighttz: error while loading shared libraries: libev.so.3: cannot open shared object file: No such file or directory
Posted on February 23rd, 2009 at 8:21 am
I just tried Lighttz, and it gave some pleasingly fast results using ab. However, I tried using HTTPerf to test the output, and it would only return as many requests as the –num-conns=X option. e.g. if you set –num-conns=5, you get 5 2xx responses, then it quits.
Do you know why this happens? Does it have something to do with not closing connections properly?
Thanks.
Posted on February 23rd, 2009 at 1:30 pm
I get the feeling the issue is related to TCP Keepalive, which I think HTTPerf uses automatically. I’ve been trying to add Keepalive support to lighttz, but can’t seem to get it working. (setsockopt…)
Any ideas?
Posted on April 23rd, 2009 at 6:29 am
Here’s nginx’s response to this:
http://www.ruby-forum.com/topic/142137#new
“Also note that lighttz does not read file at all each request.” (and that nginx might be tunable to come to similar speeds).
Cheers!
-=r
Posted on May 21st, 2009 at 5:45 am
I didn’t try nginx on linux jet, but but on freebsd it is really efficient. I couldn’t ever get it to use more than 10% cpu (user) without keep-alive.
Some hints about your testing:
nginx has a feature to serve an empty 1×1 transparent gif from memory. the other servers might have memory caching or similar capabilities making the comparison more interesting.
apache is probably not interesting at all for a comparison, because it’s architecture is focused on hosting “low-tech” scripting engines like php, which has quite different needs.
user cpu usage would be interesting to report, as we want to know how much time is spent in the application code.
thttpd would be an interesting candidate to compare against, as it also doesn’t support keep-alive requests.