A response to Preetam Jinka's nice little Go demo.
Similar basic HTTP server using Gevent/Python
from gevent import pywsgi
import md5
def md5_body(environ, start_response):
md5Hash = md5.new()
for data in environ['wsgi.input']:
md5Hash.update(data)
start_response('200 OK', [('Content-Type', 'text/html')])
yield md5Hash.digest()
server = pywsgi.WSGIServer(('', 8080), md5_body)
server.serve_forever()
Like the Go example, this is
- Implicitely Async without any extra abstractions (promises, etc)
- Relatively Simple
- Seems to work well for one request:
doug@doug-box:$ time curl -i -XPOST -d @test localhost:8080
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Content-Type: text/html
Date: Wed, 03 Sep 2014 03:32:59 GMT
Transfer-Encoding: chunked
�`�'r�"��II؊�
real 0m0.336s
user 0m0.131s
sys 0m0.055s
Unlike the Go implementation:
- It won't magically start using more threads/cores
- Its not native (so probably slower in terms of raw CPU)
- Go makes good use of CSP
- But I could write it all in IPython and test it out (ease of use of a scripting language)
One reason a Pythonista might not like either the Go or the Gevent implementation is because there's a general philosophy in Python:
Explicit is better than implicit.
In both of these cases, the non-blocking async stuff is a bit magical and implicit. I had to look at Go's http docs to figure out it is async. I think one advantage of asyncio, Python's yield from, and other abstractions is that its rather explicit to the reader that you're doing async stuff. However, Go being Go, I'm betting there's a lower likelihood of me mistaking the code for anything but async. Python being Python, its probably good to call it out.
Related Fun Reading
- My colleague Chris Brandford's friend rewriting app from Python/Twisted -> Go for network perf