| 1 | # -*- encoding: utf-8 -*- |
|---|
| 2 | # Template language benchmarks |
|---|
| 3 | # |
|---|
| 4 | # Objective: Generate a 100x10 HTML table as fast as possible and then modify bits of it using match templates. |
|---|
| 5 | # |
|---|
| 6 | # Author: Simon Cross <hodgestar@gmail.com> |
|---|
| 7 | |
|---|
| 8 | import cgi |
|---|
| 9 | import sys |
|---|
| 10 | import timeit |
|---|
| 11 | from StringIO import StringIO |
|---|
| 12 | from genshi.builder import tag |
|---|
| 13 | from genshi.template import MarkupTemplate |
|---|
| 14 | |
|---|
| 15 | try: |
|---|
| 16 | import kid |
|---|
| 17 | except ImportError: |
|---|
| 18 | kid = None |
|---|
| 19 | |
|---|
| 20 | table = [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) |
|---|
| 21 | for x in range(100)] |
|---|
| 22 | |
|---|
| 23 | genshi_tmpl = MarkupTemplate(""" |
|---|
| 24 | <table xmlns:py="http://genshi.edgewall.org/"> |
|---|
| 25 | <td py:match="td">${select('./text()')}</td> |
|---|
| 26 | <tr py:for="row in table"> |
|---|
| 27 | <td py:for="c in row.values()" py:content="c"/> |
|---|
| 28 | </tr> |
|---|
| 29 | </table> |
|---|
| 30 | """) |
|---|
| 31 | |
|---|
| 32 | def test_genshi(): |
|---|
| 33 | """Genshi template""" |
|---|
| 34 | stream = genshi_tmpl.generate(table=table) |
|---|
| 35 | stream.render('html', strip_whitespace=False) |
|---|
| 36 | |
|---|
| 37 | if kid: |
|---|
| 38 | kid_tmpl = kid.Template(""" |
|---|
| 39 | <table xmlns:py="http://purl.org/kid/ns#"> |
|---|
| 40 | <td py:match="item.tag == 'td'" py:content="item.text"/> |
|---|
| 41 | <tr py:for="row in table"> |
|---|
| 42 | <td py:for="c in row.values()" py:content="c"/> |
|---|
| 43 | </tr> |
|---|
| 44 | </table> |
|---|
| 45 | """) |
|---|
| 46 | |
|---|
| 47 | def test_kid(): |
|---|
| 48 | """Kid template""" |
|---|
| 49 | kid_tmpl.table = table |
|---|
| 50 | kid_tmpl.serialize(output='html') |
|---|
| 51 | |
|---|
| 52 | |
|---|
| 53 | def run(which=None, number=10): |
|---|
| 54 | tests = ['test_genshi', 'test_kid'] |
|---|
| 55 | |
|---|
| 56 | if which: |
|---|
| 57 | tests = filter(lambda n: n[5:] in which, tests) |
|---|
| 58 | |
|---|
| 59 | for test in [t for t in tests if hasattr(sys.modules[__name__], t)]: |
|---|
| 60 | t = timeit.Timer(setup='from __main__ import %s;' % test, |
|---|
| 61 | stmt='%s()' % test) |
|---|
| 62 | time = t.timeit(number=number) / number |
|---|
| 63 | |
|---|
| 64 | if time < 0.00001: |
|---|
| 65 | result = ' (not installed?)' |
|---|
| 66 | else: |
|---|
| 67 | result = '%16.2f ms' % (1000 * time) |
|---|
| 68 | print '%-35s %s' % (getattr(sys.modules[__name__], test).__doc__, result) |
|---|
| 69 | |
|---|
| 70 | |
|---|
| 71 | if __name__ == '__main__': |
|---|
| 72 | which = [arg for arg in sys.argv[1:] if arg[0] != '-'] |
|---|
| 73 | |
|---|
| 74 | if '-p' in sys.argv: |
|---|
| 75 | import hotshot, hotshot.stats |
|---|
| 76 | prof = hotshot.Profile("template.prof") |
|---|
| 77 | benchtime = prof.runcall(run, which, number=1) |
|---|
| 78 | stats = hotshot.stats.load("template.prof") |
|---|
| 79 | stats.strip_dirs() |
|---|
| 80 | stats.sort_stats('time', 'calls') |
|---|
| 81 | stats.print_stats() |
|---|
| 82 | else: |
|---|
| 83 | run(which) |
|---|