Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save andreif/6088558 to your computer and use it in GitHub Desktop.

Select an option

Save andreif/6088558 to your computer and use it in GitHub Desktop.

Revisions

  1. andreif revised this gist Jul 26, 2013. 1 changed file with 3 additions and 0 deletions.
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    # Performance of Flask, Tornado, GEvent, and their combinations

    Wensheng Wang, 10/1/11

    Source: http://blog.wensheng.org/2011/10/performance-of-flask-tornado-gevent-and.html

    When choosing a web framework, I pretty much have eyes set on Tornado. But I heard good things about Flask and Gevent. So I tested the performance of each and combinations of the three. I chose something just a little more advanced than a "Hello World" program to write - one that use templates. Here are the codes:
    @@ -83,6 +85,7 @@ if __name__ == "__main__":
    ```

    I have 3 template files: main.html, layout.html, and form.html. main.html "extends" layout.html and "includes" form.html. The total size of templates is about 30kB.

    The reason Flask and Tornado use different templates (main.html and main_j2.html) is that their template syntax is slightly different. Flask (jinja2) template use "{% endblock %}", "{% endfor %}", etc. while Tornado just use "{% end %}".

    I tested performance (requests per second) using ApacheBench:
  2. andreif created this gist Jul 26, 2013.
    112 changes: 112 additions & 0 deletions Performance of Flask, Tornado, GEvent, and their combinations.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,112 @@
    # Performance of Flask, Tornado, GEvent, and their combinations
    Wensheng Wang, 10/1/11
    Source: http://blog.wensheng.org/2011/10/performance-of-flask-tornado-gevent-and.html

    When choosing a web framework, I pretty much have eyes set on Tornado. But I heard good things about Flask and Gevent. So I tested the performance of each and combinations of the three. I chose something just a little more advanced than a "Hello World" program to write - one that use templates. Here are the codes:

    ## 1, Pure Flask (pure_flask.py)

    ```py
    from flask import Flask, render_template
    app = Flask(__name__)

    @app.route('/')
    def main_handler():
    return render_template('main_j2.html', messages="whatever",title="home")

    if __name__ == '__main__':
    app.run(port=8888, debug=False)
    ```

    ## 2, Pure Tornado (pure_tornado.py)

    ```py
    import os.path
    import tornado.httpserver
    import tornado.ioloop
    import tornado.web

    class MainHandler(tornado.web.RequestHandler):
    def get(self):
    self.render('main.html', page_title="", body_id="", messages="whatever",title="home")

    settings = {
    "static_path":os.path.join(os.path.dirname(__file__),'static'),
    "template_path":"templates",
    }
    application = tornado.web.Application([
    (r"/", MainHandler),
    ], **settings)

    if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()
    ```

    ## 3, Flask with Gevent (gevent_flask.py)

    ```py
    from gevent.wsgi import WSGIServer
    from pure_flask import app

    http_server = WSGIServer(('', 8888), app)
    http_server.serve_forever()
    ```

    ## 4, Flask with Tornado (tornado_flask.py)

    ```py
    from tornado.wsgi import WSGIContainer
    from tornado.httpserver import HTTPServer
    from tornado.ioloop import IOLoop
    from pure_flask import app

    http_server = HTTPServer(WSGIContainer(app))
    http_server.listen(8888)
    IOLoop.instance().start()
    ```

    ## 5, Tornado with Gevent (gevent_tornado.py)

    ```py
    import tornado.wsgi
    import gevent.wsgi
    import pure_tornado

    application = tornado.wsgi.WSGIApplication([
    (r"/", pure_tornado.MainHandler),
    ],**pure_tornado.settings)

    if __name__ == "__main__":
    server = gevent.wsgi.WSGIServer(('', 8888), application)
    server.serve_forever()
    ```

    I have 3 template files: main.html, layout.html, and form.html. main.html "extends" layout.html and "includes" form.html. The total size of templates is about 30kB.
    The reason Flask and Tornado use different templates (main.html and main_j2.html) is that their template syntax is slightly different. Flask (jinja2) template use "{% endblock %}", "{% endfor %}", etc. while Tornado just use "{% end %}".

    I tested performance (requests per second) using ApacheBench:

    ab -n 1000 -c 4 http://localhost:8888/

    and run it 5 times. The testing is done on a 6-year old dual-Opteron 254 server.

    Here are the results:

    pure_flask: 82 88 107 102 71
    pure_tornado: 144 244 241 294 290
    gevent_flask: 127 139 145 152 110
    tornado_flask: 110 88 74 92 101
    gevent_tornado: 328 555 177 273 153

    Here are the averages:

    pure_flask: 90
    pure_tornado: 242
    gevent_flask: 135
    tornado_flask: 93
    gevent_tornado: 297

    As you can see, the Tornado implementation is significantly faster than Flask. Gevent makes Tornado faster, but not by a lot.

    In the end, I like the straightforward style of Tornado and not the Flask way to write large project (using blueprints), So I sticks with Tornado.