Skip to content

Instantly share code, notes, and snippets.

@horatio-sans-serif
Created January 20, 2010 23:05
Show Gist options
  • Save horatio-sans-serif/282390 to your computer and use it in GitHub Desktop.
Save horatio-sans-serif/282390 to your computer and use it in GitHub Desktop.
# python 2.6 on linux 2.6.18
# from: http://scotdoyle.com/python-epoll-howto.html
import socket, select
EOL1 = b'\n\n'
EOL2 = b'\n\r\n'
response = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'
response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n'
response += b'Hello, world!'
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket.bind(('0.0.0.0', 8080))
serversocket.listen(5000)
serversocket.setblocking(0)
serversocket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
epoll = select.epoll()
epoll.register(serversocket.fileno(), select.EPOLLIN)
try:
connections = {}; requests = {}; responses = {}
while True:
events = epoll.poll(1)
for fileno, event in events:
if fileno == serversocket.fileno():
connection, address = serversocket.accept()
connection.setblocking(0)
epoll.register(connection.fileno(), select.EPOLLIN)
connections[connection.fileno()] = connection
requests[connection.fileno()] = b''
responses[connection.fileno()] = response
elif event & select.EPOLLIN:
requests[fileno] += connections[fileno].recv(1024)
if EOL1 in requests[fileno] or EOL2 in requests[fileno]:
epoll.modify(fileno, select.EPOLLOUT)
# TODO handle input data here
# print('-'*40 + '\n' + requests[fileno].decode()[:-2])
elif event & select.EPOLLOUT:
byteswritten = connections[fileno].send(responses[fileno])
responses[fileno] = responses[fileno][byteswritten:]
if len(responses[fileno]) == 0:
epoll.modify(fileno, 0)
connections[fileno].shutdown(socket.SHUT_RDWR)
elif event & select.EPOLLHUP:
epoll.unregister(fileno)
connections[fileno].close()
del connections[fileno]
finally:
epoll.unregister(serversocket.fileno())
epoll.close()
serversocket.close()
# MWAHAHAHAHA! (just kidding, this doesn't do anything useful)
$ /usr/local/bin/httperf --hog --timeout=60 --client=0/1 --server=localhost --port=8080 --uri=/ --rate=10000 --send-buffer=4096 --recv-buffer=16384 --num-conns=400000 --num-calls=1
httperf --hog --timeout=60 --client=0/1 --server=localhost --port=8080 --uri=/ --rate=10000 --send-buffer=4096 --recv-buffer=16384 --num-conns=400000 --num-calls=1
httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
Maximum connect burst length: 21
Total: connections 400000 requests 400000 replies 400000 test-duration 39.963 s
Connection rate: 10009.3 conn/s (0.1 ms/conn, <=81 concurrent connections)
Connection time [ms]: min 0.2 avg 2.6 max 8.4 median 3.5 stddev 1.4
Connection time [ms]: connect 0.2
Connection length [replies/conn]: 1.000
Request rate: 10009.3 req/s (0.1 ms/req)
Request size [B]: 62.0
Reply rate [replies/s]: min 10003.9 avg 10009.0 max 10016.9 stddev 4.3 (7 samples)
Reply time [ms]: response 2.4 transfer 0.0
Reply size [B]: header 101.0 content 13.0 footer 0.0 (total 114.0)
Reply status: 1xx=0 2xx=400000 3xx=0 4xx=0 5xx=0
CPU time [s]: user 12.41 system 27.55 (user 31.0% system 68.9% total 100.0%)
Net I/O: 1720.3 KB/s (14.1*10^6 bps)
Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment