user123959
user123959

Reputation: 1256

Confusion about Python Tornado's blocking

So I understand the basic idea that Tornado is itself non blocking with an event loop I/O, but that blocking IO operations like database access will result in Tornado blocking during those operations.

What I don't understand is why it seems that Tornado is blocking during non-blocking operations.

I have the following code in a handler:

class MyHandler(BaseHandler):

    def get(self):
        x = 0
        for i in xrange(0,500000000):
            x = i

        self.render("page_temp.html",
                    title="Page"
                    )

This takes ~20 seconds to load the page. If I open another browser window and try to load any other page, I get hung until the 20 second page loads. Could it be because both requests are from the same user?

Upvotes: 2

Views: 925

Answers (1)

dano
dano

Reputation: 94881

You're doing a long, CPU-bound operation directly inside your handler. tornado is single-threaded, which means it can't do CPU-bound work in the event loop thread without blocking all your other requests. If you need to do CPU-bound work, you have to do it in a background thread or process.

In order to make this method handle requests concurrently, it would need to look like this:

from concurrent.futures import ThreadPoolExecutor
from tornado import gen
from tornado.web import RequestHandler

executor = ThreadPoolExecutor(8) # 8 Threads in the pool

class ThreadPoolHandler(RequestHandler):

    def _do_loop(self):
        x = 0
        for i in xrange(0,500000000):
            x = i

    @gen.coroutine
    def get(self):
        yield executor.submit(self._do_loop) # Run through the loop without blocking tornado
        self.render("page_temp.html",
                    title="Page"
                    )

By using a ThreadPoolExecutor to run the expensive for-loop in a background thread, tornado can continue to serve other requests while waiting for the CPU work to complete.

Upvotes: 4

Related Questions