Repository URL to install this package:
|
Version:
2.11 ▾
|
import unittest
import time
import os
import re
from .utils import text_
re_amp = re.compile(r'&(?!([A-Za-z]+|#[0-9]+);)')
BIGTABLE_ZPT = """\
<table xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal">
<tr tal:repeat="row python: options['table']">
<td tal:repeat="c python: row.values()">
<span tal:define="d python: c + 1"
tal:attributes="class python: 'column-' + str(d)"
tal:content="python: d" />
</td>
</tr>
</table>"""
MANY_STRINGS_ZPT = """\
<table xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal">
<tr tal:repeat="i python: xrange(1000)">
<td tal:content="string: number ${i}" />
</tr>
</table>
"""
HELLO_WORLD_ZPT = """\
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal">
<body>
<h1>Hello, world!</h1>
</body>
</html>
"""
I18N_ZPT = """\
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
<body>
<div tal:repeat="i python: xrange(10)">
<div i18n:translate="">
Hello world!
</div>
<div i18n:translate="hello_world">
Hello world!
</div>
<div i18n:translate="">
<sup>Hello world!</sup>
</div>
</div>
</body>
</html>
"""
def benchmark(title):
def decorator(f):
def wrapper(*args):
print(
"==========================\n " \
"%s\n==========================" % \
title)
return f(*args)
return wrapper
return decorator
def timing(func, *args, **kwargs):
t1 = t2 = time.time()
i = 0
while t2 - t1 < 3:
func(**kwargs)
func(**kwargs)
func(**kwargs)
func(**kwargs)
i += 4
t2 = time.time()
return float(10 * (t2 - t1)) / i
START = 0
END = 1
TAG = 2
def yield_tokens(table=None):
index = []
tag = index.append
_re_amp = re_amp
tag(START)
yield "<", "html", "", ">\n"
for r in table:
tag(START)
yield "<", "tr", "", ">\n"
for c in r.values():
d = c + 1
tag(START)
yield "<", "td", "", ">\n"
_tmp5 = d
if not isinstance(_tmp5, unicode):
_tmp5 = str(_tmp5)
if ('&' in _tmp5):
if (';' in _tmp5):
_tmp5 = _re_amp.sub('&', _tmp5)
else:
_tmp5 = _tmp5.replace('&', '&')
if ('<' in _tmp5):
_tmp5 = _tmp5.replace('<', '<')
if ('>' in _tmp5):
_tmp5 = _tmp5.replace('>', '>')
if ('"' in _tmp5):
_tmp5 = _tmp5.replace('"', '"')
_tmp5 = "column-%s" % _tmp5
_tmp = d
if (_tmp.__class__ not in (str, unicode, int, float, )):
raise
if (_tmp is not None):
if not isinstance(_tmp, unicode):
_tmp = str(_tmp)
if ('&' in _tmp):
if (';' in _tmp):
_tmp = _re_amp.sub('&', _tmp)
else:
_tmp = _tmp.replace('&', '&')
if ('<' in _tmp):
_tmp = _tmp.replace('<', '<')
if ('>' in _tmp):
_tmp = _tmp.replace('>', '>')
tag(START)
t = ["classicism"]
yield "<", "span", " ", t[0], '="', _tmp5, '"', ">\n"
tag(END)
yield "</", "span", ">\n"
tag(END)
yield "</", "td", ">\n"
tag(END)
yield "</", "tr", ">\n"
tag(END)
yield "</", "html", ">\n"
def yield_tokens_dict_version(**kwargs):
index = []
tag = index.append
_re_amp = re_amp
tag(START)
yield "<", "html", "", ">\n"
for r in kwargs['table']:
kwargs['r'] = r
tag(START)
yield "<", "tr", "", ">\n"
for c in kwargs['r'].values():
kwargs['d'] = c + 1
tag(START)
yield "<", "td", "", ">\n"
_tmp5 = kwargs['d']
if not isinstance(_tmp5, unicode):
_tmp5 = str(_tmp5)
if ('&' in _tmp5):
if (';' in _tmp5):
_tmp5 = _re_amp.sub('&', _tmp5)
else:
_tmp5 = _tmp5.replace('&', '&')
if ('<' in _tmp5):
_tmp5 = _tmp5.replace('<', '<')
if ('>' in _tmp5):
_tmp5 = _tmp5.replace('>', '>')
if ('"' in _tmp5):
_tmp5 = _tmp5.replace('"', '"')
_tmp5 = "column-%s" % _tmp5
_tmp = kwargs['d']
if (_tmp.__class__ not in (str, unicode, int, float, )):
raise
if (_tmp is not None):
if not isinstance(_tmp, unicode):
_tmp = str(_tmp)
if ('&' in _tmp):
if (';' in _tmp):
_tmp = _re_amp.sub('&', _tmp)
else:
_tmp = _tmp.replace('&', '&')
if ('<' in _tmp):
_tmp = _tmp.replace('<', '<')
if ('>' in _tmp):
_tmp = _tmp.replace('>', '>')
tag(START)
t = ["classicism"]
yield "<", "span", " ", t[0], '="', _tmp5, '"', ">\n"
tag(END)
yield "</", "span", ">\n"
tag(END)
yield "</", "td", ">\n"
tag(END)
yield "</", "tr", ">\n"
tag(END)
yield "</", "html", ">\n"
def yield_stream(table=None):
_re_amp = re_amp
yield START, ("html", "", "\n"), None
for r in table:
yield START, ("tr", "", "\n"), None
for c in r.values():
d = c + 1
yield START, ("td", "", "\n"), None
_tmp5 = d
if not isinstance(_tmp5, unicode):
_tmp5 = str(_tmp5)
if ('&' in _tmp5):
if (';' in _tmp5):
_tmp5 = _re_amp.sub('&', _tmp5)
else:
_tmp5 = _tmp5.replace('&', '&')
if ('<' in _tmp5):
_tmp5 = _tmp5.replace('<', '<')
if ('>' in _tmp5):
_tmp5 = _tmp5.replace('>', '>')
if ('"' in _tmp5):
_tmp5 = _tmp5.replace('"', '"')
_tmp5 = "column-%s" % _tmp5
_tmp = d
if (_tmp.__class__ not in (str, unicode, int, float, )):
raise
if (_tmp is not None):
if not isinstance(_tmp, unicode):
_tmp = str(_tmp)
if ('&' in _tmp):
if (';' in _tmp):
_tmp = _re_amp.sub('&', _tmp)
else:
_tmp = _tmp.replace('&', '&')
if ('<' in _tmp):
_tmp = _tmp.replace('<', '<')
if ('>' in _tmp):
_tmp = _tmp.replace('>', '>')
yield START, ("span", "", _tmp, " ", "class", _tmp5), None
yield END, ("span", "", "\n"), None
yield END, ("td", "", "\n"), None
yield END, ("tr", "", "\n"), None
yield END, ("html", "", "\n"), None
from itertools import chain
def bigtable_python_tokens(table=None, renderer=None):
iterable = renderer(table=table)
stream = chain(*iterable)
return "".join(stream)
def bigtable_python_stream(table=None, renderer=None):
stream = renderer(table=table)
return "".join(stream_output(stream))
def bigtable_python_stream_with_filter(table=None, renderer=None):
stream = renderer(table=table)
return "".join(stream_output(uppercase_filter(stream)))
def uppercase_filter(stream):
for kind, data, pos in stream:
if kind is START:
data = (data[0], data[1], data[2].upper(),) + data[3:]
elif kind is END:
data = (data[0], data[1], data[2].upper())
elif kind is TAG:
raise NotImplemented
yield kind, data, pos
def stream_output(stream):
for kind, data, pos in stream:
if kind is START:
tag = data[0]
yield "<%s" % tag
l = len(data)
# optimize for common cases
if l == 3:
pass
elif l == 6:
yield '%s%s="%s"' % (data[3], data[4], data[5])
else:
i = 3
while i < l:
yield '%s%s="%s"' % (data[i], data[i + 1], data[i + 2])
i += 3
yield "%s>%s" % (data[1], data[2])
elif kind is END:
yield "</%s%s>%s" % data
elif kind is TAG:
raise NotImplemented
class Benchmarks(unittest.TestCase):
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)]
def setUp(self):
# set up i18n component
from zope.i18n import translate
from zope.i18n.interfaces import INegotiator
from zope.i18n.interfaces import ITranslationDomain
from zope.i18n.negotiator import Negotiator
from zope.i18n.simpletranslationdomain import SimpleTranslationDomain
from zope.i18n.tests.test_negotiator import Env
from zope.tales.tales import Context
self.env = Env(('klingon', 'da', 'en', 'fr', 'no'))
class ZopeI18NContext(Context):
def translate(self, msgid, domain=None, context=None,
mapping=None, default=None):
context = self.vars['options']['env']
return translate(msgid, domain, mapping,
context=context, default=default)
def _getContext(self, contexts=None, **kwcontexts):
if contexts is not None:
if kwcontexts:
kwcontexts.update(contexts)
else:
kwcontexts = contexts
return ZopeI18NContext(self, kwcontexts)
def _pt_getEngineContext(namespace):
self = namespace['template']
engine = self.pt_getEngine()
return _getContext(engine, namespace)
import zope.component
zope.component.provideUtility(Negotiator(), INegotiator)
catalog = SimpleTranslationDomain('domain')
zope.component.provideUtility(catalog, ITranslationDomain, 'domain')
self.files = os.path.abspath(os.path.join(__file__, '..', 'input'))
@staticmethod
def _chameleon(body, **kwargs):
from .zpt.template import PageTemplate
return PageTemplate(body, **kwargs)
@staticmethod
def _zope(body):
from zope.pagetemplate.pagetemplatefile import PageTemplate
template = PageTemplate()
template.pt_edit(body, 'text/xhtml')
return template
@benchmark(text_("BIGTABLE [python]"))
def test_bigtable(self):
options = {'table': self.table}
t_chameleon = timing(self._chameleon(BIGTABLE_ZPT), options=options)
print("chameleon: %7.2f" % t_chameleon)
t_chameleon_utf8 = timing(
self._chameleon(BIGTABLE_ZPT, encoding='utf-8'), options=options)
print("chameleon (utf-8): %7.2f" % t_chameleon_utf8)
t_tokens = timing(
bigtable_python_tokens, table=self.table, renderer=yield_tokens)
print("token: %7.2f" % t_tokens)
t_tokens_dict_version = timing(
bigtable_python_tokens, table=self.table,
renderer=yield_tokens_dict_version)
print("token (dict): %7.2f" % t_tokens_dict_version)
t_stream = timing(
bigtable_python_stream, table=self.table, renderer=yield_stream)
print("stream: %7.2f" % t_stream)
t_zope = timing(self._zope(BIGTABLE_ZPT), table=self.table)
print("zope.pagetemplate: %7.2f" % t_zope)
print(" %7.1fX" % (t_zope / t_chameleon))
print("--------------------------")
print("check: %d vs %d" % (
len(self._chameleon(BIGTABLE_ZPT)(options=options)),
len(self._zope(BIGTABLE_ZPT)(table=self.table))))
print("--------------------------")
@benchmark(text_("MANY STRINGS [python]"))
def test_many_strings(self):
t_chameleon = timing(self._chameleon(MANY_STRINGS_ZPT))
print("chameleon: %7.2f" % t_chameleon)
t_zope = timing(self._zope(MANY_STRINGS_ZPT))
print("zope.pagetemplate: %7.2f" % t_zope)
print(" %7.1fX" % (t_zope / t_chameleon))
print("--------------------------")
print("check: %d vs %d" % (
len(self._chameleon(MANY_STRINGS_ZPT)()),
len(self._zope(MANY_STRINGS_ZPT)())))
print("--------------------------")
@benchmark(text_("HELLO WORLD"))
def test_hello_world(self):
t_chameleon = timing(self._chameleon(HELLO_WORLD_ZPT)) * 1000
print("chameleon: %7.2f" % t_chameleon)
t_zope = timing(self._zope(HELLO_WORLD_ZPT)) * 1000
print("zope.pagetemplate: %7.2f" % t_zope)
print(" %7.1fX" % (t_zope / t_chameleon))
print("--------------------------")
print("check: %d vs %d" % (
len(self._chameleon(HELLO_WORLD_ZPT)()),
len(self._zope(HELLO_WORLD_ZPT)())))
print("--------------------------")
@benchmark(text_("I18N"))
def test_i18n(self):
from zope.i18n import translate
t_chameleon = timing(
self._chameleon(I18N_ZPT),
translate=translate,
language="klingon") * 1000
print("chameleon: %7.2f" % t_chameleon)
t_zope = timing(self._zope(I18N_ZPT), env=self.env) * 1000
print("zope.pagetemplate: %7.2f" % t_zope)
print(" %7.1fX" % (t_zope / t_chameleon))
@benchmark(text_("COMPILATION"))
def test_compilation(self):
template = self._chameleon(HELLO_WORLD_ZPT)
def chameleon_cook_and_render(template=template):
template.cook(HELLO_WORLD_ZPT)
template()
t_chameleon = timing(chameleon_cook_and_render) * 1000
print("chameleon: %7.2f" % t_chameleon)
template = self._zope(HELLO_WORLD_ZPT)
def zope_cook_and_render(templte=template):
template._cook()
template()
t_zope = timing(zope_cook_and_render) * 1000
print("zope.pagetemplate: %7.2f" % t_zope)
print(" %0.3fX" % (t_zope / t_chameleon))
def start():
result = unittest.TestResult()
test = unittest.makeSuite(Benchmarks)
test.run(result)
for error in result.errors:
print("Error in %s...\n" % error[0])
print(error[1])
for failure in result.failures:
print("Failure in %s...\n" % failure[0])
print(failure[1])