[gnet-devel] GNet HTTP server class



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]