Suppose I have a long running function:
def long_running_function():
result_future = Future()
result = 0
for i in xrange(500000):
result += i
result_future.set_result(result)
return result_future
I have a get function in a handler that prints the user with the above result of a for loop that adds all the number in the xrange:
@gen.coroutine
def get(self):
print "start"
self.future = long_running_function()
message = yield self.future
self.write(str(message))
print "end"
If I run the above code on two web browsers simultaneously, I get:
start
end
start
end
Which seems to be blocking. From my understanding, the @gen.coroutine
and the yield
statement does not block the IOLoop in the get function, however, if any functions that is inside the co-routine that is blocking, then it blocks the IOLoop.
Hence the other thing I did is to turn the long_running_function
into a callback, and using the yield gen.Task
instead.
@gen.coroutine
def get(self):
print "start"
self.future = self.long_running_function
message = yield gen.Task(self.future, None)
self.write(str(message))
print "end"
def long_running_function(self, arguments, callback):
result = 0
for i in xrange(50000000):
result += i
return callback(result)
This doesn't cut too, it gives me:
start
end
start
end
I can use threads to execute those in parallel, but it doesn't seem the way to go, because I might be opening a lot of threads, and according to Tornado's user guide, it may be expensive.
How do people write async libraries for Tornado?
If the blocking function is CPU-bound (as your for/xrange example is), then threads (or processes) are the only way to make it non-blocking. Creating a thread per incoming request is expensive, but making a small ThreadPoolExecutor to handle all CPU-bound operations is not.
To make a function non-blocking without using threads, the function must be event-driven: it must be waiting on some external event (such as network I/O) so that it can be awoken when that event occurs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With