Boa is a single-tasking HTTP server. Boa does not fork a copy of itself or spawn a thread to handle each incoming connection, but rather internally multiplexes the connections. Boa only forks for CGI programs, automatic directory generation, and automatic file gunzipping, each of which must be a separate process. The primary design goals of Boa are speed and security, in the sense of “can’t be subverted by a malicious user”, not “fine grained access control and encrypted communications”. Boa is not intended as a feature-packed server; if you want one of those, Boa is probably not the right choice.
Introduction: What is Boa?
Boa is written in C and uses the GNU autoconf system to provide a portable code base. It has been reported to run out-of-the-box on many different flavors of UN*X, and with minor tweaking on many more. Currently Boa is developed on a Linux platform, on a variety of distributions, most notably RedHat Linux, Debian GNU/Linux, andGentoo Linux. Additionally, Boa is available under FreeBSD 4.6 as a port. Boa has also been reported to run on OpenBSD, HP/UX, Solaris 7 and 8, AIX, and even the Cygwin environment for Windows. An earlier release of Boa was even ported to run under DOS!
Boa excels at certain types of web serving, notably static documents, which means documents served directly off of disk, without involving additional processes. Though desgined before 100Mbit ethernet, Boa can easily saturate 100Mbit Ethernet links on even modest hardware. Boa was designed before such hardware was readily available, and was specifically designed to use resources efficiently. In fact, Boa is actually one of the oldest actively developed web servers!
Boa was written sometime in the early 1990’s by Paul Philips. More accurately, the first announcement I could find regarding Boa dates back to September 20, 1995, in which Paul announces v0.90 of “The
Boa webserver”. Unfortunately, I cannot locate any release announcement prior to this, although Boa was undoubtably under development earlier than this. Shortly thereafter version 0.91 was released.
In 1996, I encountered Boa in my quest for a lightweight http server that fit the following rigorous criteria: it must be able to run well on the modest hardware I had available and I should be able to look at the code and at least pretend that I knew what was going on. The hardware I had available was a Zeos Intel i386 with 2MB of RAM and 120MB of very slow drive storage. After some initial research, I downloaded and tried to compile several servers, including Apache, NCSA, thttpd and Boa (version 0.91). I wasn’t able to get Apache to run in a satisfactory manner; I felt it was much too heavy for the hardware. NCSA ran slowly, and with thttpd and Boa I encountered various bugs. I resolved initially tried fixing some of the bugs, but I wasn’t able to understand thttpd’s code enough to be able to effectively contribute. When I turned to Boa, I immediately felt that the code was much cleaner. After some
time, I felt I was successful in my attempted bug fix, so I wrote Paul Philips. He replied that two others had taken 0.91, continued
development and released 0.92, which he hadn’t even seen yet. I took the information he provided me, and contacted Larry Doolittle. I contributed a patch or two, and gradually became more involved.
Version 0.92 was the next major release, and was the first by someone other than Paul. Larry Doolittle handled this release. Version 0.92 went through several iterations, and the “official” release, 0.92o was on December 23, 1996. There were a number of point releases after that, finally ending at 0.92q. Today, you can find still many variants of the 0.92 release series in various hardware and software devices.
Version 0.93 was released shortly thereafter, and was treated as the “development” version for a long time – more than four years,
in fact. Finally, on January 17, 2000 version 0.94 was released. As was the usual case, 0.94 went through a few minor point releases, but solidified very nicely.
Version 0.94 represented an enormous amount of work, and many hundreds of CVS commits, but the result was a significantly faster, cleaner, and more robust webserver.
What does “high performance” mean?
In the context of web serving, a “high performance” webserver features low latency and high throughput. For some types of documents, Boa can do this very well. Using the benchmark systems and hardware described below, Boa boasts an excellent average latency of under 425ms under heavy load (that’s on a Duron 700 client and servers with RealTek rtl8139 10/100 cards with a hub). That’s pretty snappy, folks. Additionally, it maintains low latency while providing high throughput, typically saturating 100MBit connections, regardless of file size or concurrency.
What about Boa’s resource consumption?
Boa has minimal resource requirements. The stripped binary size on Linux using gcc 2.95.3 and GNU libc 2.2.5 is 61K (495K statically linked). Using a library such as uClibc Boa can get much smaller – 92K statically linked. In conjuction with very low memory requirements, Boa is ideal for machines without a great deal of horsepower. Boa is particularly well suited to the embedded market, and can currently be found on numerous hardware devices (including the ThinkNIC and a series of Axis web cameras). Larry Doolittle has been successful in running Boa on (seemingly) modest hardware, including a 200MHz StrongARM-based unit roughly the size of a credit card (http://recycle.lbl.gov/~ldoolitt/bse/). Boa once powered the “World’s Smallest Web Server”, located at http://wearables.stanford.edu/.
My current hardware, consisting of AMD Duron 700’s with 384MB of RAM, RealTek 8139 and SiS900 chipset-based NICs, a LinkSys 10/100 hub, and Linux 2.4 is probably considered mid-range. For Boa, this hardware configuration is more than adequate. The VmSize of Boa on this workstation at this moment is 1696kB, 85% of which is libraries. The VmData size is currently 108kB. Boa consumes roughly 20kB of memory per concurrent connection. Thus, going full-tilt with (for example) 500 simultaneous connections, Boa would consume (1700 + 20 * 500) = 11700 == roughly 12MB of RAM. Determining total memory consumption of a statically compiled Boa is left as an exercise for the reader (determine the “resting” memory consumption and add roughly 20KB per active connection).
As an example of Boa’s resource utilization, please consult the following table:
|Server||Stripped Binary Size||VmSize||External Libraries|
A very recent addition to my hardware includes two Netgear GA-302T Gig-E cards, connected to each other. Over these cards, on the same hardware, I have been able to achieve impressive results:
Results from running “ZeusBench” with a file size of 105165 bytes, 215 concurrency, using keepalive. 10,000 fetches:
Document Length: 105165
Concurency Level: 215
Time taken for tests: 24.748 seconds
Complete requests: 10000
Failed requests: 0
Keep-Alive requests: 10002
Bytes transfered: 1064119164
HTML transfered: 1061744679
Requests per seconds: 404.07
Transfer rate: 42998.19 kb/s
Connnection Times (ms)
min avg max
Connect: 0 14 9029
Total: 388 526 9547
And from ‘apache bench’:
Concurrency Level: 215
Time taken for tests: 23.298 seconds
Complete requests: 10000
Failed requests: 0
Broken pipe errors: 0
Keep-Alive requests: 10001
Total transferred: 1063465974 bytes
HTML transferred: 1061094751 bytes
Requests per second: 429.22 [#/sec] (mean)
Time per request: 500.91 [ms] (mean)
Time per request: 2.33 [ms] (mean, across all concurrent requests)
Transfer rate: 45646.23 [Kbytes/sec] received
Distilling the numbers means that I was able to achieve 43-45% of the maximum theoretical bandwidth of Gig-E. Also note that at this
time, both Gig-E cards had MTUs of 1500 bytes, as the author was unable to get the cards to behave with the 9000 byte Jumbo Frame MTUs. Keep in mind that both ZeusBench and ApacheBench are each only single processes, and therefore can’t accurately reflect “true” load on machine from many disparite machines. However, also keep in mind that while serving static content, Boa will never introduce a load of more than 1.0 to the system, vitally important to some applications. In fact, I have received many reports from people detailing how Boa has helped them reduce load on their servers. One administrator wrote to describe how he reduced load on his main Apache servers from 200-300 down to 10-20 by serving static content from dedicated Boa servers.
How is performance measured?
For rough estimates of raw capability and throughput, I run benchmarks over localhost. Because these benchmarks aren’t meaningful in real-world situations, I perform most benchmarks over a 100MBit ethernet LAN (or my new Gig-E LAN.)
I use zb (ZeusBench, the source code that formed the basis for ab, ApacheBench) to form the basis of most of my tests. For quick, one-off tests, I invariably run zb with the same parameters to keep as few variables changing as possible and provide the closest comparable numbers between runs.
To help automate the process of executing potentially thousands of zb runs, changing only one variable at a time, I wrote a python wrapper around zb. I also wrote some gnuplot programs which use this data, and the final result is a very good picture at how the web server performs under various concurrency and file size variations. The result is that Boa’s performance scales in an essentially inverse direct relationship to concurrency and file size increases. What that means is that Boa’s performance is very easy to predict under specific concurrency and file size loads, because the statistics are so consistent.
Interaction with External Processes
While Boa is a general purpose server, it does not contain special support for much more than the HTTP/1.0 (tentative and conditional support for HTTP/1.1 is in more recent versions of Boa) and CGI/1.1 specifications. Thus, any language that can be used as a CGI will work just fine, and this includes the popular scripting languages Python, Perl, and PHP.
At this time there is no direct support for PHP, and there is no analog to mod_perl, mod_snake/mod_python, or other loadable modules. It it hoped that a future version of Boa will support loadable modules, making Boa a much more versatile httpd.
Some Boa aficionados have experimented with embedding Perl or Python directly in Boa, although neither of these experiments is ready for prime-time just yet.
Prior to the 0.94 release, several branches of Boa were made to explore different process models and features, including threading, name-based virtualhost support, authentication and loadable modules to name a few. In fact, there are dozens of currently unrealized features that have already been implemented in one branch or another that might someday make it into a Boa release. In fact, there are outstanding requests for various features that have already been implemented in one of the branches that I hope will make it into the first 0.95.0 release.
Many people have asked me (and probably Larry, too), why there hasn’t been a 1.0 release. I don’t have a very good answer for that, but suffice it to say, we feel our 0.94 release is better than most 1.0 releases.
About the Author
Jon Nelson lives and works in his home state of Wisconsin with his family, and spends all together too much time in front of a computer screen. The author would like to thank Martin A. Brown, co-worker and friend, for his editing efforts.