Permalink
Browse files

Add some speed tests.

  • Loading branch information...
1 parent 55b26cd commit cffc0ea05823292a37a23138a7304f0bceda2b63 @SimonSapin SimonSapin committed Apr 1, 2012
Showing with 132 additions and 0 deletions.
  1. +16 −0 tinycss/parsing.py
  2. +116 −0 tinycss/tests/speed.py
View
16 tinycss/parsing.py
@@ -62,6 +62,22 @@ def strip_whitespace(tokens):
return tokens
+def remove_whitespace(tokens):
+ """Remove any top-level whitespace in a token list.
+
+ Whitespace tokens inside recursive :class:`~.token_data.ContainerToken`
+ are preserved.
+
+ :param tokens:
+ A list of :class:`~.token_data.Token` or
+ :class:`~.token_data.ContainerToken`.
+ :return:
+ A new sub-sequence of the list.
+
+ """
+ return [token for token in tokens if token.type != 'S']
+
+
def validate_value(tokens):
"""Validate a property value.
View
116 tinycss/tests/speed.py
@@ -0,0 +1,116 @@
+# coding: utf8
+"""
+ Speed tests
+ -----------
+
+ Note: this file is not named test_*.py as it is not part of the
+ test suite ran by pytest.
+
+ :copyright: (c) 2012 by Simon Sapin.
+ :license: BSD, see LICENSE for more details.
+"""
+
+
+from __future__ import unicode_literals, division
+
+import sys
+import os.path
+import contextlib
+import timeit
+import functools
+
+from cssutils import parseString
+
+from .. import tokenizer
+from ..css21 import CSS21Parser
+from ..parsing import remove_whitespace
+
+
+CSS_REPEAT = 4
+TIMEIT_REPEAT = 3
+TIMEIT_NUMBER = 20
+
+
+def load_css():
+ filename = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'docs', '_static', 'custom.css')
+ with open(filename, 'rb') as fd:
+ return b'\n'.join([fd.read()] * CSS_REPEAT)
+
+
+# Pre-load so that I/O is not measured
+CSS = load_css()
+
+
+@contextlib.contextmanager
+def install_tokenizer(name):
+ original = tokenizer.tokenize_flat
+ try:
+ tokenizer.tokenize_flat = getattr(tokenizer, name)
+ yield
+ finally:
+ tokenizer.tokenize_flat = original
+
+
+def parse(tokenizer_name):
+ with install_tokenizer(tokenizer_name):
+ stylesheet = CSS21Parser().parse_stylesheet_bytes(CSS)
+ result = []
+ for rule in stylesheet.rules:
+ selector = ''.join(s.as_css for s in rule.selector)
+ declarations = [
+ (declaration.name, len(list(remove_whitespace(declaration.value))))
+ for declaration in rule.declarations]
+ result.append((selector, declarations))
+ return result
+
+parse_cython = functools.partial(parse, 'cython_tokenize_flat')
+parse_python = functools.partial(parse, 'python_tokenize_flat')
+
+
+def parse_cssutils():
+ stylesheet = parseString(CSS)
+ result = []
+ for rule in stylesheet.cssRules:
+ selector = rule.selectorText
+ declarations = [
+ (declaration.name, len(list(declaration.propertyValue)))
+ for declaration in rule.style.getProperties(all=True)]
+ result.append((selector, declarations))
+ return result
+
+
+def check_consistency():
+ #import pprint
+ #pprint.pprint(parse_python())
+ result = parse_cython()
+ assert len(result) > 0
+ assert parse_python() == result
+ assert parse_cssutils() == result
+ version = '.'.join(map(str, sys.version_info[:3]))
+ print('Python {}, consistency OK.'.format(version))
+
+
+def time(function):
+ seconds = timeit.Timer(function).repeat(TIMEIT_REPEAT, TIMEIT_NUMBER)
+ miliseconds = int(min(seconds) * 1000)
+ return miliseconds
+
+
+def run():
+ data_set = [
+ ('tinycss + speedups ', parse_cython),
+ ('tinycss WITHOUT speedups', parse_python),
+# ('cssutils ', parse_cssutils),
+ ]
+ label, function = data_set.pop(0)
+ ref = time(function)
+ print('{} {} ms'.format(label, ref))
+ for label, function in data_set:
+ result = time(function)
+ print('{} {} ms {:.2f}x'.format(label, result, result / ref))
+
+
+if __name__ == '__main__':
+ check_consistency()
+ run()

0 comments on commit cffc0ea

Please sign in to comment.