Created
June 4, 2012 14:52
-
-
Save karanlyons/2868852 to your computer and use it in GitHub Desktop.
Node vs. Gevent (Sync and Async)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# encoding: utf-8 | |
# $ brew install libev | |
# $ pip install http://gevent.googlecode.com/files/gevent-1.0b2.tar.gz | |
# $ chmod +x ./gevent_fib.py | |
# $ ./gevent_fib.py | |
import time | |
from gevent.pywsgi import WSGIServer | |
from gevent import monkey | |
monkey.patch_all() | |
def syncfib(n): # Six lines, one named function. | |
if n < 2: | |
return n | |
else: | |
return syncfib(n - 2) + syncfib(n - 1) | |
def asyncfib(n): # Eight lines, one named function, one call to `time.sleep()` (patched to `gevent.sleep()`). | |
if n < 2: | |
return n | |
else: | |
time.sleep() # Explicitely yielding (canonically `gevent.sleep()`, but with monkey-patching it's the same; perhaps slightly slower for the extra reference.). | |
return asyncfib(n - 2) + asyncfib(n - 1) | |
def wait(n): # Again, for testing...also four lines. | |
time.sleep(n) # `monkey.patch_all()` made this non-blocking. More accurately, it now blocks the greenlet running this code instead of the entire interpreter. | |
return n | |
def application(environ, start_response): | |
start_response('200 OK', [('Content-Type', 'text/html')]) | |
path = environ['PATH_INFO'] | |
version = path[1:2] | |
try: | |
n = int(path[3:]) | |
except ValueError: | |
n = 25 | |
if version == 's': # Sync | |
return ["Sync: %i" % syncfib(n)] | |
elif version == 'a': # Async | |
return ["Async: %i" % asyncfib(n)] | |
elif version == 'w': # Wait | |
return ["Slept: %i second%s." % (wait(n), 's' if n != 1 else '')] | |
else: | |
return ["Try:<br /><a href='http://localhost:8000/s/25'>sync</a><br /><a href='http://localhost:8000/a/25'>async</a><br /><a href='http://localhost:8000/w/25'>wait</a>"] | |
if __name__ == '__main__': | |
app = WSGIServer(('', 8000), application, log=None) | |
print "Serving on http://127.0.0.1:8000/." | |
try: | |
app.serve_forever() | |
except KeyboardInterrupt: | |
app.stop() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
// $ brew install node | |
// $ curl http://npmjs.org/install.sh | sh | |
// $ npm install async | |
// $ chmod +x ./node_fib | |
// $ ./node_fib | |
var http = require('http'); | |
var url = require('url'); | |
var async = require('async'); | |
var syncfib = function (n) { // Nine lines, one named function. | |
if (n < 2) { | |
return n; | |
} | |
else { | |
return syncfib(n - 2) + syncfib(n - 1); | |
} | |
} | |
var asyncfib = function (n, callback) { // 14 lines, one named function, three anonymous functions. Two calls to `process.nextTick()` inside of functions. | |
if (n < 2) { // Node conventions: 1st arg is usually an error/null, last arg is a callback (if required). | |
callback(null, n); | |
} | |
else { | |
async.series([ | |
function (callback) { process.nextTick(function() { asyncfib(n - 2, callback); }); }, // Without `process.nexTick()` you'll hit the call stack limit very quickly. | |
function (callback) { process.nextTick(function() { asyncfib(n - 1, callback); }); } | |
], function (error, results) { | |
callback(null, results[0] + results[1]); | |
}); | |
} | |
} | |
var wait = function (n, callback) { // Just for testing...and two lines. | |
setTimeout(callback, n * 1000); | |
} | |
http.createServer(function (request, response) { | |
response.writeHead(200, {'Content-Type': 'text/html'}); | |
var path = url.parse(request.url, true).pathname; | |
var version = path.slice(1,2); | |
var n = parseInt(path.slice(3)) || 25; | |
switch (version) { | |
case 's': // Sync | |
response.end("Sync: " + syncfib(n)); | |
break; | |
case 'a': // Async | |
asyncfib(n, function (error, results) { response.end("Async: " + results); }); | |
break; | |
case 'w': // Wait | |
wait(n, function () { response.end("Slept: " + n + " second" + (n != 1 ? "s" : "") + "."); }); | |
break; | |
default: // Some helpful links | |
response.end("Try:<br /><a href='http://localhost:8000/s/25'>sync</a><br /><a href='http://localhost:8000/a/25'>async</a><br /><a href='http://localhost:8000/w/25'>wait</a>"); | |
break; | |
} | |
}).listen(8000); | |
console.log("Serving on http://127.0.0.1:8000/."); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've probably done something wrong here and so unfairly favored one side or the other. But I've done my best not to.