Python模板性能评测
本篇主要是对django, jinja, jinja2, mako和cheetah五大python模板引擎性能的评测。对于这几个引擎,分别测试它们渲染字符串,变量替换,以及循环处理的速度,所有结果输出均为unicode,变量替换均需html转义,所有模板中,只有django默认开启了html转义,其它模板需要显式地打开。所有测试均不计算模板加载、编译时间,只计算渲染时间,因为模板通常只会加载一次,却会渲染多次。下面是所有模板引擎分别运行每个测试用例10000次所花的时间:
str var for jinja2: 0.138658046722 0.640381097794 0.969153165817 mako: 0.389529943466 1.019780159 1.04453492165 cheetah: 0.350683927536 1.73273897171 2.3115170002 jinja: 0.102370023727 1.48854589462 3.32249498367 django: 0.168296098709 3.63100194931 13.236135006
import re, sysfrom timeit import Timerfrom django.conf import settingssettings.configure()def render_django(tmpl_str, tmpl_ctx): from django.template import Template, Context tmpl = Template(tmpl_str) return lambda: tmpl.render(Context(tmpl_ctx))def render_jinja2(tmpl_str, tmpl_ctx): from jinja2 import Environment tmpl = Environment(autoescape=True).from_string(tmpl_str) return lambda: tmpl.render(tmpl_ctx)def render_jinja(tmpl_str, tmpl_ctx): from jinja import Environment tmpl = Environment(auto_escape=True).from_string(tmpl_str) return lambda: tmpl.render(tmpl_ctx)def render_mako(tmpl_str, tmpl_ctx): from mako.template import Template tmpl = Template(tmpl_str, default_filters=['h']) return lambda: tmpl.render(**tmpl_ctx)def render_cheetah(tmpl_str, tmpl_ctx): from Cheetah.Template import Template from Cheetah.Filters import WebSafe tmpl = type(Template(tmpl_str)) return lambda: tmpl(searchList=[tmpl_ctx], filter=WebSafe).respond()django_syntax = dict(var='{{ %s }}', for_start='{%% for %s in %s %%}', for_end='{%% endfor %%}')jinja2_syntax = jinja_syntax = django_syntaxcheetah_syntax = dict(var='$%s', for_start='#for $%s in $%s', for_end='#end for')mako_syntax = dict(var='${%s}', for_start='%% for %s in %s:', for_end='%% endfor')str_tmpl = 'a' * 1000var_tmpl = ''.join(['%s @var,var%s@ ' % ('a'*100, i) for i in range(10)])for_tmpl = '''\@for_start,item,item_list@ %s @var,item@@for_end@''' % ('a'*100)syntax_list = [ ('jinja2', jinja2_syntax, render_jinja2), ('mako', mako_syntax, render_mako), ('cheetah', cheetah_syntax, render_cheetah), ('jinja', jinja_syntax, render_jinja), ('django', django_syntax, render_django),]tmpl_list = [ ('str', str_tmpl, {}), ('var', var_tmpl, dict([('var%s'%i, '<foobar%s>'%i) for i in range(10)])), ('for', for_tmpl, dict(item_list=range(20))),]RE_TMPL = re.compile('@([\w,]+)@')def bench(count=10000): for name, syntax, render in syntax_list: emit('%10s: ' % name) for tmpl_type, tmpl_str, tmpl_ctx in tmpl_list: def _sub(m): s = m.group(1).split(',') return syntax[s[0]] % tuple(s[1:]) tmpl_str = RE_TMPL.sub(_sub, tmpl_str) render_tmpl = render(tmpl_str, tmpl_ctx) emit('%-15s ' % Timer(render_tmpl).timeit(count)) emit('\n')def emit(s): sys.stdout.write(s) sys.stdout.flush() bench()