Thursday, July 19, 2012

Python Fastest Template Engine

What is the fastest template system for Python? Django, Kid, Genshi are quite slow in compare to those used in this post. See also:
  • Comprehensive benchmarks for various template include, extends and widget directives are here.
The benchmark is based on wheezy.template big table test for rendering a 10x1000 HTML table in unicode. Latest available versions (November 23, 2013):
  1. chameleon 2.13_1
  2. cheetah 2.4.4
  3. django 1.6
  4. jinja2 2.7.1
  5. mako 0.9.0
  6. durusworks qpy 1.2
  7. spitfire 0.7.15
  8. tenjin 1.1.1
  9. tornado 3.1.1
  10. web2py 2.0.9
  11. wheezy.template 0.1.135
Let setup virtualenv environment:
virtualenv env
env/bin/easy_install -O2 chameleon cheetah django \
  jinja2 mako tenjin webext tornado wheezy.html \
  wheezy.template
Download bigtable.py test:
wget https://bitbucket.org/akorn/wheezy.template/raw/tip/demos/bigtable/bigtable.py
And run it:
env/bin/python bigtable.py
Raw numbers (Intel Core 2 Duo @ 2.4 GHz x 2; OS X 10.9):
cpython 2.7
                     msec    rps  tcalls  funcs
chameleon           75.07  13.32  161031     24
cheetah            196.16   5.10  225019     22
django            1365.07   0.73 1752082     56
jinja2              75.45  13.25   60018     26
list_append         12.38  80.78   63007      9
list_extend         10.58  94.56   23007      9
mako                52.08  19.20   93035     36
qpy_list_append    282.92   3.53  505023     14
spitfire            43.33  23.08  124016     23
tenjin              14.29  69.98   43010     13
tornado             89.71  11.15  233021     23
web2py             106.45   9.39  295015     20
wheezy_template     12.53  79.82   63009     11

pypy 2.2
                     msec    rps  tcalls  funcs
chameleon           52.89  18.91  193036     25
cheetah            399.48   2.50  755039     33
django             230.43   4.34 1744083     54
jinja2              35.93  27.83  123018     27
list_append         23.63  42.32  103007     10
list_extend         27.29  36.64   63007     10
mako                22.13  45.20  153037     39
qpy_list_append            not installed
spitfire            65.87  15.18  123015     21
tenjin             230.13   4.35   13010     11
tornado             46.80  21.37  233021     23
web2py              30.16  33.15  295015     20
wheezy_template     24.92  40.13  103009     12

cpython 3.3
                     msec    rps  tcalls  funcs
chameleon           76.11  13.14  182033     25
cheetah                    not installed
django            1378.04   0.73 1672083     52
jinja2              66.45  15.05   60020     27
list_append         15.66  63.87   63008     10
list_extend         14.31  69.87   23008     10
mako                54.12  18.48   93036     37
qpy_list_append    257.25   3.89  495025     16
spitfire                   not installed
tenjin              53.10  18.83  123012     16
tornado            192.47   5.20  353023     23
web2py                     not installed
wheezy_template     16.24  61.58   63010     12
tcalls - a total number of calls, funcs - a number of unique functions used.

The wheezy.template outperforms jinja2 / mako templates significantly while offering the power in: template inheritance, include and import directives plus context preprocessor. Take a look at a real world example available in this demo (source). Looking for other benchmarks? Take a look at python benchmarks for routing, url reverse and web frameworks.

16 comments:

  1. Great.

    How about str() or html escape?
    I had found that the bottle neck of template engine is in str() or html escape, not in list.append or ''.join().
    (See http://www.slideshare.net/kwatch/how-to-create-a-highspeed-template-engine-in-python for details.)

    If you have time, could you try webext?
    http://www.kuwata-lab.com/tenjin/pytenjin-users-guide.html#tips-webext
    Or enforce tenjin.Engine not to call str() function?

    engine = tenjin.Engine(tostrfunc='')

    # I'm the author of Tenjin and above presentation slide.

    By the way, Jinja2, Mako, Tenjin, and wheezy.template have enough performance for web application. I believe that the performance bottle-neck of web application is not in them.
    But... it is fun to pursue high performance of template engine!

    ReplyDelete
    Replies
    1. Thank you for your comments. I have added webext optimization for tenjin. Please notice, there is huge performance degradation once I have webext installed for pypy (the benchmark for pypy does not have it installed).

      Delete
    2. Note, webext can not be installed into python3.3 virtual environment. Here are few errors:

      webext.c:89:18: error: ‘PyString_Type’ undeclared (first use in this function)
      webext.c:97:23: error: ‘PyInt_Type’ undeclared (first use in this function)

      Delete
  2. It would be interesting to see Cheetah on this list: http://cheetahtemplate.org/

    ReplyDelete
  3. For some reason when I run your bigtable.py benchmark to compare the lot against QPY (https://www.mems-exchange.org/software/), wheezy_template is performing roughly on par with list_append/list_extend. Any ideas why? This on a Linux Mint Debian Edition VM, Python 3.3.2.

    QPY btw is turning in 60 rps vs 29 rps for list_*. I'll put examples up on my site shortly.

    ReplyDelete
    Replies
    1. The wheezy.template translates markup to the code identical to list_append example.

      The difference in results is related to CPU switching for given process, thus you need stick it with one processor (use taskset) and make higher number of iterations (eliminate django first).

      Delete
  4. I've put up a post with some code samples and the results obtained for all the packages I'd installed in a Python 3.3.2 virtual instance:

    http://mikewatkins.ca/2013/06/12/python-fastest-template-engine/

    QPY is fast but isn't a traditional HTML or text templating system as most know them these days. Thankfully when a different itch needs scratching there's a nice selection of web tools for Python developers that are "fast enough".

    ReplyDelete
    Replies
    1. The top of the post has a reference to in-depth benchmarks for template engine directives like include, extends and widgets.

      Delete
    2. The python unicode string concatenation via join is inefficient due to continuous buffer re-locations. While wheezy.template remains pure python implementation it rely on python core efficiency.

      While evaluating impact of such improvement to real world application the result was so minimal that I decided to keep thing as is.

      Good to know QPY went even further by utilizing C optimizations.

      Delete
  5. Another template system that'd be good to have up there is Spitfire.
    https://code.google.com/p/spitfire/

    ReplyDelete
    Replies
    1. I have updated bigtable source code to include Spitfire.

      Delete
  6. Is wheezy.template compatible with Google App Engine?

    ReplyDelete
  7. Hi, maybe i'll have more success here. I can't figure out how to use a variable as a key in whezzy:

    http://stackoverflow.com/questions/21760517/wheezy-template-dictionary-variable-lookup

    ReplyDelete