Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[svn r589] refactoring of benchmark setup, add 'bench' target to Make…

…file

--HG--
branch : trunk
  • Loading branch information...
commit 64137145920a1b2cbe7a35ddcc2edd5fef366b45 1 parent 43757a3
scoder authored
Showing with 101 additions and 45 deletions.
  1. +5 −0 Makefile
  2. +96 −45 bench.py
View
5 Makefile
@@ -18,6 +18,9 @@ test_build: build
test_inplace: inplace
$(PYTHON) test.py $(TESTFLAGS) $(TESTOPTS)
+bench_inplace: inplace
+ PYTHONPATH="src:$$PYTHONPATH" $(PYTHON) bench.py
+
ftest_build: build
$(PYTHON) test.py -f $(TESTFLAGS) $(TESTOPTS)
@@ -27,6 +30,8 @@ ftest_inplace: inplace
# XXX What should the default be?
test: test_inplace
+bench: bench_inplace
+
ftest: ftest_inplace
clean:
View
141 bench.py
@@ -4,46 +4,61 @@
from lxml import etree
class BenchMark(object):
- ALL_TREES = (1,2,3)
- def setup(self, trees=ALL_TREES):
- atoz = string.ascii_lowercase
- def tag(ns='y'):
- for i in count():
- yield "{%s}z%d" % (ns,i)
-
- if 1 in trees:
- # tree with some 2nd level and loads of 3rd level children
- root = etree.Element('{a}root')
- for ch1 in atoz:
- el = etree.SubElement(root, "{b}"+ch1)
- for ch2 in atoz:
- for i in range(100):
- etree.SubElement(el, "{c}%s%03d" % (ch2, i))
-
- self._root1 = root
- self._tree1 = etree.ElementTree(root)
-
- if 2 in trees:
- # tree with loads of 2nd level and fewer 3rd level children
- root = etree.Element('{x}root')
- for ch1 in atoz:
- for i in range(100):
- el = etree.SubElement(root, "{y}%s%03d" % (ch1, i))
- for ch2 in atoz:
- etree.SubElement(el, "{z}"+ch2)
+ atoz = string.ascii_lowercase
- self._root2 = root
- self._tree2 = etree.ElementTree(root)
+ def setup(self, trees=()):
+ if not trees:
+ trees = self._all_trees()
- if 3 in trees:
- # deep tree with constant number of children
- root = etree.Element('{x}root')
- children = [root]
- for i in range(10):
- children = list(imap(etree.SubElement, children*3, tag()))
+ for tree in trees:
+ setup = getattr(self, '_setup_tree%d' % tree)
+ root = setup()
+ setattr(self, '_root%d' % tree, root)
+ setattr(self, '_tree%d' % tree, etree.ElementTree(root))
- self._root3 = root
- self._tree3 = etree.ElementTree(root)
+ def _all_trees(self):
+ all_trees = []
+ for name in dir(self):
+ if name.startswith('_setup_tree'):
+ all_trees.append(int(name[11:]))
+ return all_trees
+
+ def _setup_tree1(self):
+ "tree with some 2nd level and loads of 3rd level children"
+ root = etree.Element('{a}root')
+ atoz = self.atoz
+ for ch1 in atoz:
+ el = etree.SubElement(root, "{b}"+ch1)
+ for ch2 in atoz:
+ for i in range(100):
+ etree.SubElement(el, "{c}%s%03d" % (ch2, i))
+ return root
+
+ def _setup_tree2(self):
+ "tree with loads of 2nd level and fewer 3rd level children"
+ root = etree.Element('{x}root')
+ atoz = self.atoz
+ SubElement = etree.SubElement
+ for ch1 in atoz:
+ for i in range(100):
+ el = SubElement(root, "{y}%s%03d" % (ch1, i))
+ for ch2 in atoz:
+ SubElement(el, "{z}"+ch2)
+ return root
+
+ def _setup_tree3(self):
+ "deep tree with constant number of children per node"
+ root = etree.Element('{x}root')
+ SubElement = etree.SubElement
+ tags = self._tags
+ children = [root]
+ for i in range(10):
+ children = list(imap(SubElement, children*3, tags()))
+ return root
+
+ def _tags(ns='y'):
+ for i in count():
+ yield "{%s}z%d" % (ns,i)
def cleanup(self):
for name in dir(self):
@@ -56,6 +71,7 @@ def benchmarks(self):
A benchmark is a tuple containing a method name and a list of tree
numbers. Trees are prepared by the setup function.
"""
+ all_trees = self._all_trees()
benchmarks = []
for name in dir(self):
if not name.startswith('bench_'):
@@ -69,19 +85,47 @@ def benchmarks(self):
for tree_set in tree_sets:
benchmarks.append((name, map(int, tree_set.split(','))))
else:
- for tree in bench.ALL_TREES:
- benchmarks.append((name, [tree]))
+ try:
+ function = getattr(method, 'im_func', method)
+ arg_count = method.func_code.co_argcount / 2
+ except AttributeError:
+ arg_count = 1
+ for trees in self._permutations(all_trees, arg_count):
+ benchmarks.append((name, trees))
return benchmarks
+ def _permutations(self, seq, count):
+ def _permutations(prefix, remainder, count):
+ if count == 0:
+ return [ prefix[:] ]
+ count -= 1
+ perms = []
+ prefix.append(None)
+ for pos, el in enumerate(remainder):
+ new_remainder = remainder[:pos] + remainder[pos+1:]
+ prefix[-1] = el
+ perms.extend( _permutations(prefix, new_remainder, count) )
+ prefix.pop()
+ return perms
+ return _permutations([], seq, count)
+
+
+############################################################
+# Benchmarks:
+############################################################
class LxmlBenchMark(BenchMark):
def bench_append_from_document(self, tree1, root1, tree2, root2):
- "1,2 2,3 1,3" # needs trees 1 and 2, or 2 and 3, or 1 and 3
+ # == "1,2 2,3 1,3 3,1 3,2 2,1" # trees 1 and 2, or 2 and 3, or ...
for el in root2:
root1.append(root2[0])
+ def bench_insert_from_document(self, tree1, root1, tree2, root2):
+ for el in root2:
+ root1.insert(len(root1)/2, root2[0])
+
def bench_rotate_children(self, tree, root):
- #"1 2 3" # runs on any single tree independently
+ # == "1 2 3" # runs on any single tree independently
for i in range(100):
root.append(root[0])
@@ -89,13 +133,20 @@ def bench_reorder(self, tree, root):
for i in range(1,len(root)/2):
root[-i:-i] = root[0]
+ def bench_clear(self, tree, root):
+ root.clear()
+
if __name__ == '__main__':
bench = LxmlBenchMark()
benchmarks = bench.benchmarks()
if len(sys.argv) > 1:
- selected = [ "bench_%s" % name for name in sys.argv[1:] ]
+ selected = []
+ for name in sys.argv[1:]:
+ if not name.startswith('bench_'):
+ name = 'bench_' + name
+ selected.append(name)
benchmarks = [ b for b in benchmarks if b[0] in selected ]
benchmarks.sort() # by name and tree tuple
@@ -106,16 +157,16 @@ def bench_reorder(self, tree, root):
timer = timeit.Timer(
"bench.%s(%s)" % (bench_name, bench_args),
- "from __main__ import bench ; bench.setup(%s)" % str(tuple(tree_set))
+ "from __main__ import bench ; bench.setup(%s) ; gc.enable()" % str(tuple(tree_set))
)
print "%-25s (T%-6s)" % (bench_name[6:], ',T'.join(imap(str, tree_set))[:6]),
sys.stdout.flush()
- result = timer.repeat(3, 100)
+ result = timer.repeat(3, 50)
bench.cleanup()
for t in result:
print "%8.4f" % t,
- print "msec/pass, avg: %8.4f" % (sum(result) / len(result))
+ print "msec/pass, best: %8.4f" % min(result)
Please sign in to comment.
Something went wrong with that request. Please try again.