Skip to content
Newer
Older
100644 317 lines (298 sloc) 7.76 KB
32a910f @mitsuhiko added spitfire to bench and did some more refactoring
authored
1 """\
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
2 This benchmark compares some python templating engines with Jinja 2 so
3 that we get a picture of how fast Jinja 2 is for a semi real world
32a910f @mitsuhiko added spitfire to bench and did some more refactoring
authored
4 template. If a template engine is not installed the test is skipped.\
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
5 """
de6bf71 @mitsuhiko some performance improvements
authored
6 import sys
32a910f @mitsuhiko added spitfire to bench and did some more refactoring
authored
7 import cgi
00d5d21 @mitsuhiko some more stuff for jinja2
authored
8 from timeit import Timer
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
9 from jinja2 import Environment as JinjaEnvironment
00d5d21 @mitsuhiko some more stuff for jinja2
authored
10
de6bf71 @mitsuhiko some performance improvements
authored
11 context = {
12 'page_title': 'mitsuhiko\'s benchmark',
13 'table': [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) for x in range(1000)]
14 }
00d5d21 @mitsuhiko some more stuff for jinja2
authored
15
16 jinja_template = JinjaEnvironment(
17 line_statement_prefix='%',
18 variable_start_string="${",
19 variable_end_string="}"
20 ).from_string("""\
21 <!doctype html>
22 <html>
23 <head>
de6bf71 @mitsuhiko some performance improvements
authored
24 <title>${page_title|e}</title>
00d5d21 @mitsuhiko some more stuff for jinja2
authored
25 </head>
26 <body>
27 <div class="header">
28 <h1>${page_title|e}</h1>
29 </div>
30 <ul class="navigation">
31 % for href, caption in [
32 ('index.html', 'Index'),
33 ('downloads.html', 'Downloads'),
34 ('products.html', 'Products')
35 ]
36 <li><a href="${href|e}">${caption|e}</a></li>
37 % endfor
38 </ul>
39 <div class="table">
40 <table>
41 % for row in table
42 <tr>
43 % for cell in row
44 <td>${cell}</td>
45 % endfor
46 </tr>
47 % endfor
48 </table>
49 </div>
50 </body>
51 </html>\
52 """)
53
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
54 def test_jinja():
55 jinja_template.render(context)
56
57 try:
58 from django.conf import settings
59 settings.configure()
60 from django.template import Template as DjangoTemplate, Context as DjangoContext
61 except ImportError:
62 test_django = None
63 else:
64 django_template = DjangoTemplate("""\
00d5d21 @mitsuhiko some more stuff for jinja2
authored
65 <!doctype html>
66 <html>
67 <head>
de6bf71 @mitsuhiko some performance improvements
authored
68 <title>{{ page_title }}</title>
00d5d21 @mitsuhiko some more stuff for jinja2
authored
69 </head>
70 <body>
71 <div class="header">
72 <h1>{{ page_title }}</h1>
73 </div>
74 <ul class="navigation">
75 {% for href, caption in navigation %}
76 <li><a href="{{ href }}">{{ caption }}</a></li>
77 {% endfor %}
78 </ul>
79 <div class="table">
80 <table>
81 {% for row in table %}
82 <tr>
83 {% for cell in row %}
84 <td>{{ cell }}</td>
85 {% endfor %}
86 </tr>
87 {% endfor %}
88 </table>
89 </div>
90 </body>
91 </html>\
92 """)
93
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
94 def test_django():
95 c = DjangoContext(context)
96 c['navigation'] = [('index.html', 'Index'), ('downloads.html', 'Downloads'),
97 ('products.html', 'Products')]
98 django_template.render(c)
99
100 try:
101 from mako.template import Template as MakoTemplate
102 except ImportError:
103 test_mako = None
104 else:
105 mako_template = MakoTemplate("""\
00d5d21 @mitsuhiko some more stuff for jinja2
authored
106 <!doctype html>
107 <html>
108 <head>
de6bf71 @mitsuhiko some performance improvements
authored
109 <title>${page_title|h}</title>
00d5d21 @mitsuhiko some more stuff for jinja2
authored
110 </head>
111 <body>
112 <div class="header">
113 <h1>${page_title|h}</h1>
114 </div>
115 <ul class="navigation">
116 % for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]:
117 <li><a href="${href|h}">${caption|h}</a></li>
118 % endfor
119 </ul>
120 <div class="table">
121 <table>
122 % for row in table:
123 <tr>
124 % for cell in row:
125 <td>${cell}</td>
126 % endfor
127 </tr>
128 % endfor
129 </table>
130 </div>
131 </body>
132 </html>\
449167d @mitsuhiko fixed a bug in the compiler
authored
133 """)
00d5d21 @mitsuhiko some more stuff for jinja2
authored
134
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
135 def test_mako():
136 mako_template.render(**context)
137
138 try:
139 from genshi.template import MarkupTemplate as GenshiTemplate
140 except ImportError:
141 test_genshi = None
142 else:
143 genshi_template = GenshiTemplate("""\
de6bf71 @mitsuhiko some performance improvements
authored
144 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/">
145 <head>
146 <title>${page_title}</title>
147 </head>
148 <body>
149 <div class="header">
150 <h1>${page_title}</h1>
151 </div>
152 <ul class="navigation">
153 <li py:for="href, caption in [
154 ('index.html', 'Index'),
155 ('downloads.html', 'Downloads'),
156 ('products.html', 'Products')]"><a href="${href}">${caption}</a></li>
157 </ul>
158 <div class="table">
159 <table>
160 <tr py:for="row in table">
161 <td py:for="cell in row">${cell}</td>
162 </tr>
163 </table>
164 </div>
165 </body>
166 </html>\
167 """)
168
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
169 def test_genshi():
170 genshi_template.generate(**context).render('html', strip_whitespace=False)
171
172 try:
173 from Cheetah.Template import Template as CheetahTemplate
174 except ImportError:
175 test_cheetah = None
176 else:
177 cheetah_template = CheetahTemplate("""\
de6bf71 @mitsuhiko some performance improvements
authored
178 #import cgi
179 <!doctype html>
180 <html>
181 <head>
182 <title>$cgi.escape($page_title)</title>
183 </head>
184 <body>
185 <div class="header">
186 <h1>$cgi.escape($page_title)</h1>
187 </div>
188 <ul class="navigation">
189 #for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]:
190 <li><a href="$cgi.escape($href)">$cgi.escape($caption)</a></li>
191 #end for
192 </ul>
193 <div class="table">
194 <table>
195 #for $row in $table:
196 <tr>
197 #for $cell in $row:
198 <td>$cell</td>
199 #end for
200 </tr>
201 #end for
202 </table>
203 </div>
204 </body>
205 </html>\
206 """, searchList=[dict(context)])
00d5d21 @mitsuhiko some more stuff for jinja2
authored
207
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
208 def test_cheetah():
209 unicode(cheetah_template)
00d5d21 @mitsuhiko some more stuff for jinja2
authored
210
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
211 try:
212 import tenjin
213 except ImportError:
214 test_tenjin = None
215 else:
216 tenjin_template = tenjin.Template()
217 tenjin_template.convert("""\
218 <!doctype html>
219 <html>
220 <head>
221 <title>${page_title}</title>
222 </head>
223 <body>
224 <div class="header">
225 <h1>${page_title}</h1>
226 </div>
227 <ul class="navigation">
228 <?py for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]: ?>
229 <li><a href="${href}">${caption}</a></li>
230 <?py #end ?>
231 </ul>
232 <div class="table">
233 <table>
234 <?py for row in table: ?>
235 <tr>
236 <?py for cell in row: ?>
237 <td>#{cell}</td>
238 <?py #end ?>
239 </tr>
240 <?py #end ?>
241 </table>
242 </div>
243 </body>
244 </html>\
245 """)
de6bf71 @mitsuhiko some performance improvements
authored
246
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
247 def test_tenjin():
248 from tenjin.helpers import escape, to_str
249 tenjin_template.render(context, locals())
00d5d21 @mitsuhiko some more stuff for jinja2
authored
250
32a910f @mitsuhiko added spitfire to bench and did some more refactoring
authored
251 try:
252 from spitfire.compiler import util as SpitfireTemplate
253 from spitfire.compiler.analyzer import o2_options as spitfire_optimizer
254 except ImportError:
255 test_spitfire = None
256 else:
257 spitfire_template = SpitfireTemplate.load_template("""\
258 <!doctype html>
259 <html>
260 <head>
261 <title>$cgi.escape($page_title)</title>
262 </head>
263 <body>
264 <div class="header">
265 <h1>$cgi.escape($page_title)</h1>
266 </div>
267 <ul class="navigation">
268 #for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]
269 <li><a href="$cgi.escape($href)">$cgi.escape($caption)</a></li>
270 #end for
271 </ul>
272 <div class="table">
273 <table>
274 #for $row in $table
275 <tr>
276 #for $cell in $row
277 <td>$cell</td>
278 #end for
279 </tr>
280 #end for
281 </table>
282 </div>
283 </body>
284 </html>\
285 """, 'spitfire_tmpl', spitfire_optimizer, {'enable_filters': False})
286 spitfire_context = dict(context, **{'cgi': cgi})
287
288 def test_spitfire():
289 spitfire_template(search_list=[spitfire_context]).main()
290
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
291 sys.stdout.write('\r' + '\n'.join((
de6bf71 @mitsuhiko some performance improvements
authored
292 '=' * 80,
293 'Template Engine BigTable Benchmark'.center(80),
32a910f @mitsuhiko added spitfire to bench and did some more refactoring
authored
294 '=' * 80,
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
295 __doc__,
de6bf71 @mitsuhiko some performance improvements
authored
296 '-' * 80
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
297 )) + '\n')
c9705c2 @mitsuhiko all unittests pass, the special and dependency lookups have their own…
authored
298
299
300 for test in 'jinja', 'mako', 'tenjin', 'spitfire', 'django', 'genshi', 'cheetah':
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
301 if locals()['test_' + test] is None:
32a910f @mitsuhiko added spitfire to bench and did some more refactoring
authored
302 sys.stdout.write(' %-20s*not installed*\n' % test)
2feed1d @mitsuhiko there is now a workaround in the compiler that makes sure it's possib…
authored
303 continue
00d5d21 @mitsuhiko some more stuff for jinja2
authored
304 t = Timer(setup='from __main__ import test_%s as bench' % test,
305 stmt='bench()')
32a910f @mitsuhiko added spitfire to bench and did some more refactoring
authored
306 sys.stdout.write(' >> %-20s<running>' % test)
de6bf71 @mitsuhiko some performance improvements
authored
307 sys.stdout.flush()
32a910f @mitsuhiko added spitfire to bench and did some more refactoring
authored
308 sys.stdout.write('\r %-20s%.4f seconds\n' % (test, t.timeit(number=20) / 20))
309 sys.stdout.write('-' * 80 + '\n')
310 sys.stdout.write('''\
311 WARNING: The results of this benchmark are useless to compare the
312 performance of template engines and should not be taken seriously in any
313 way. It's testing the performance of simple loops and has no real-world
314 usefulnes. It only used to check if changes on the Jinja code affect
315 performance in a good or bad way and how it roughly compares to others.
316 ''' + '=' * 80 + '\n')
Something went wrong with that request. Please try again.