[gnet-devel] GNet HTTP server class
- From: Jeff Garzik <jeff garzik org>
- To: gnet-devel-list gnome org
- Subject: [gnet-devel] GNet HTTP server class
- Date: Wed, 28 Nov 2007 14:13:52 -0500
In contrast to (I'm guessing) a lot of GNet users, I'm actually
interested in GNet for applications on the server side, rather than the
client side.
One of my long term ideas is for a "sister project" to GNet, call it
GNet-Protocols for lack of a better name, that would implement various
client and server protocols on top of GNet.
To that end, here is this afternoon's work, a working embedded HTTP
server class, GSHTTP (Gnet Server HTTP):
http://www.kernel.org/pub/linux/kernel/people/jgarzik/misc/srvhttp-0.1.tar.gz
The example application runs in the foreground (it's not a daemon), and
serves a single file from RAM on port 8080:
./httpd ~/tmp/foo.html text/html
results in
http://myhost:8080/foo.html
all other URLs return 404 not found.
Just like GNet's GServer class, this new GSHTTP class is a thin wrapper
on top of GServer and GConn. It parses an HTTP request with the help of
GURI, parses the HTTP headers, and then passes that result to the user's
HTTP request function for processing. The user directly talks to a
GConn object from that point on.
I have attached ApacheBench results on a gigabit network between two
fast computers, for 1,000,000 requests of a 4K file. The results are
decent for a couple hours of work, but not great. There are WAY too
many per-request memory allocations and copies. As a result, I was
actually bounded not by network bandwidth but CPU usage -- the app was
consuming 100% CPU (it is single-threaded) during the ApacheBench run.
Some of that is the app's fault, but some of that is GNet. In
high-volume server applications, the only data copies that take place
occur when calling system calls (read, write). The server app _never_
copies data, if it doesn't have to. Ditto for allocations. That was my
motivation for adding gnet_conn_write_direct(), and I am thinking about
adding gnet_conn_read_direct() as well. GURI does too many string
copies and allocations to be used on a per-HTTP-request basis, too, IMO.
Anyway... comments on any of this, or my code, is welcome. It's not
intended to be highly polished code, but it works under stress tests,
and it illustrates an example of how to do a GNet lightweight protocol
class.
Jeff
[jgarzik core ~]$ ab -c8 -n1000000 http://pretzel:8080/index.html
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/
Benchmarking pretzel (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Finished 1000000 requests
Server Software:
Server Hostname: pretzel
Server Port: 8080
Document Path: /index.html
Document Length: 4383 bytes
Concurrency Level: 8
Time taken for tests: 124.536151 seconds
Complete requests: 1000000
Failed requests: 0
Write errors: 0
Total transferred: 4468000000 bytes
HTML transferred: 4383000000 bytes
Requests per second: 8029.80 [#/sec] (mean)
Time per request: 0.996 [ms] (mean)
Time per request: 0.125 [ms] (mean, across all concurrent requests)
Transfer rate: 35036.26 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 10
Processing: 0 0 0.4 0 11
Waiting: 0 0 0.4 0 11
Total: 0 0 0.4 0 11
Percentage of the requests served within a certain time (ms)
50% 0
66% 0
75% 0
80% 0
90% 0
95% 1
98% 2
99% 2
100% 11 (longest request)
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]