# basic.py - basic benchmarks adapted from Genshi # Copyright (C) 2006 Edgewall Software # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # 3. The name of the author may not be used to endorse or promote # products derived from this software without specific prior # written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from cgi import escape import os from StringIO import StringIO import sys import timeit __all__ = ['mako', 'mako_inheritance', 'cheetah', 'django', 'myghty', 'genshi', 'kid'] def genshi(dirname, verbose=False): from genshi.template import TemplateLoader loader = TemplateLoader([dirname], auto_reload=False) template = loader.load('template.html') def render(): data = dict(title='Just a test', user='joe', items=['Number %d' % num for num in range(1, 15)]) return template.generate(**data).render('xhtml') if verbose: print render() return render def myghty(dirname, verbose=False): from myghty import interp interpreter = interp.Interpreter(component_root=dirname) def render(): data = dict(title='Just a test', user='joe', items=['Number %d' % num for num in range(1, 15)]) buffer = StringIO() interpreter.execute("template.myt", request_args=data, out_buffer=buffer) return buffer.getvalue() if verbose: print render() return render def mako(dirname, verbose=False): from mako.template import Template from mako.lookup import TemplateLookup lookup = TemplateLookup(directories=[dirname], filesystem_checks=False, disable_unicode=True) template = lookup.get_template('template.html') def render(): return template.render(title="Just a test", user="joe", list_items=[u'Number %d' % num for num in range(1,15)]) if verbose: print template.code, render() return render mako_inheritance = mako def cheetah(dirname, verbose=False): from Cheetah.Template import Template filename = os.path.join(dirname, 'template.tmpl') template = Template(file=filename) def render(): template.__dict__.update({'title': 'Just a test', 'user': 'joe', 'list_items': [u'Number %d' % num for num in range(1, 15)]}) return template.respond() if verbose: print dir(template) print template.generatedModuleCode() print render() return render def django(dirname, verbose=False): from django.conf import settings settings.configure(TEMPLATE_DIRS=[os.path.join(dirname, 'templates')]) from django import template, templatetags from django.template import loader templatetags.__path__.append(os.path.join(dirname, 'templatetags')) tmpl = loader.get_template('template.html') def render(): data = {'title': 'Just a test', 'user': 'joe', 'items': ['Number %d' % num for num in range(1, 15)]} return tmpl.render(template.Context(data)) if verbose: print render() return render def kid(dirname, verbose=False): import kid kid.path = kid.TemplatePath([dirname]) template = kid.Template(file='template.kid') def render(): template = kid.Template(file='template.kid', title='Just a test', user='joe', items=['Number %d' % num for num in range(1, 15)]) return template.serialize(output='xhtml') if verbose: print render() return render def run(engines, number=2000, verbose=False): basepath = os.path.abspath(os.path.dirname(__file__)) for engine in engines: dirname = os.path.join(basepath, engine) if verbose: print '%s:' % engine.capitalize() print '--------------------------------------------------------' else: print '%s:' % engine.capitalize(), t = timeit.Timer(setup='from __main__ import %s; render = %s(r"%s", %s)' % (engine, engine, dirname, verbose), stmt='render()') time = t.timeit(number=number) / number if verbose: print '--------------------------------------------------------' print '%.2f ms' % (1000 * time) if verbose: print '--------------------------------------------------------' if __name__ == '__main__': engines = [arg for arg in sys.argv[1:] if arg[0] != '-'] if not engines: engines = __all__ verbose = '-v' in sys.argv if '-p' in sys.argv: import hotshot, hotshot.stats prof = hotshot.Profile("template.prof") benchtime = prof.runcall(run, engines, number=100, verbose=verbose) stats = hotshot.stats.load("template.prof") stats.strip_dirs() stats.sort_stats('time', 'calls') stats.print_stats() else: run(engines, verbose=verbose)