Blame benchmark/benchbase.py

rpm-build d9acb6
import sys, re, string, time, copy, gc
rpm-build d9acb6
from itertools import *
rpm-build d9acb6
import time
rpm-build d9acb6
rpm-build d9acb6
try:
rpm-build d9acb6
    izip
rpm-build d9acb6
except NameError:
rpm-build d9acb6
    izip = zip  # Py3
rpm-build d9acb6
rpm-build d9acb6
def exec_(code, glob):
rpm-build d9acb6
    if sys.version_info[0] >= 3:
rpm-build d9acb6
        exec(code, glob)
rpm-build d9acb6
    else:
rpm-build d9acb6
        exec("exec code in glob")
rpm-build d9acb6
rpm-build d9acb6
rpm-build d9acb6
TREE_FACTOR = 1 # increase tree size with '-l / '-L' cmd option
rpm-build d9acb6
rpm-build d9acb6
_TEXT  = "some ASCII text" * TREE_FACTOR
rpm-build d9acb6
_UTEXT = u"some klingon: \F8D2" * TREE_FACTOR
rpm-build d9acb6
_ATTRIBUTES = {
rpm-build d9acb6
    '{attr}test1' : _TEXT,
rpm-build d9acb6
    '{attr}test2' : _TEXT,
rpm-build d9acb6
    'bla1'        : _TEXT,
rpm-build d9acb6
    'bla2'        : _TEXT,
rpm-build d9acb6
    'bla3'        : _TEXT
rpm-build d9acb6
    }
rpm-build d9acb6
rpm-build d9acb6
rpm-build d9acb6
def initArgs(argv):
rpm-build d9acb6
    global TREE_FACTOR
rpm-build d9acb6
    try:
rpm-build d9acb6
        argv.remove('-l')
rpm-build d9acb6
        # use large trees
rpm-build d9acb6
        TREE_FACTOR *= 2
rpm-build d9acb6
    except ValueError:
rpm-build d9acb6
        pass
rpm-build d9acb6
rpm-build d9acb6
    try:
rpm-build d9acb6
        argv.remove('-L')
rpm-build d9acb6
        # use LARGE trees
rpm-build d9acb6
        TREE_FACTOR *= 2
rpm-build d9acb6
    except ValueError:
rpm-build d9acb6
        pass
rpm-build d9acb6
rpm-build d9acb6
############################################################
rpm-build d9acb6
# benchmark decorators
rpm-build d9acb6
############################################################
rpm-build d9acb6
rpm-build d9acb6
def with_attributes(*use_attributes):
rpm-build d9acb6
    "Decorator for benchmarks that use attributes"
rpm-build d9acb6
    vmap = {False : 0, True : 1}
rpm-build d9acb6
    values = [ vmap[bool(v)] for v in use_attributes ]
rpm-build d9acb6
    def set_value(function):
rpm-build d9acb6
        try:
rpm-build d9acb6
            function.ATTRIBUTES.update(values)
rpm-build d9acb6
        except AttributeError:
rpm-build d9acb6
            function.ATTRIBUTES = set(values)
rpm-build d9acb6
        return function
rpm-build d9acb6
    return set_value
rpm-build d9acb6
rpm-build d9acb6
def with_text(no_text=False, text=False, utext=False):
rpm-build d9acb6
    "Decorator for benchmarks that use text"
rpm-build d9acb6
    values = []
rpm-build d9acb6
    if no_text:
rpm-build d9acb6
        values.append(0)
rpm-build d9acb6
    if text:
rpm-build d9acb6
        values.append(1)
rpm-build d9acb6
    if utext:
rpm-build d9acb6
        values.append(2)
rpm-build d9acb6
    def set_value(function):
rpm-build d9acb6
        try:
rpm-build d9acb6
            function.TEXT.add(values)
rpm-build d9acb6
        except AttributeError:
rpm-build d9acb6
            function.TEXT = set(values)
rpm-build d9acb6
        return function
rpm-build d9acb6
    return set_value
rpm-build d9acb6
rpm-build d9acb6
def onlylib(*libs):
rpm-build d9acb6
    "Decorator to restrict benchmarks to specific libraries"
rpm-build d9acb6
    def set_libs(function):
rpm-build d9acb6
        if libs:
rpm-build d9acb6
            function.LIBS = libs
rpm-build d9acb6
        return function
rpm-build d9acb6
    return set_libs
rpm-build d9acb6
rpm-build d9acb6
def serialized(function):
rpm-build d9acb6
    "Decorator for benchmarks that require serialized XML data"
rpm-build d9acb6
    function.STRING = True
rpm-build d9acb6
    return function
rpm-build d9acb6
rpm-build d9acb6
def children(function):
rpm-build d9acb6
    "Decorator for benchmarks that require a list of root children"
rpm-build d9acb6
    function.CHILDREN = True
rpm-build d9acb6
    return function
rpm-build d9acb6
rpm-build d9acb6
def nochange(function):
rpm-build d9acb6
    "Decorator for benchmarks that do not change the XML tree"
rpm-build d9acb6
    function.NO_CHANGE = True
rpm-build d9acb6
    return function
rpm-build d9acb6
rpm-build d9acb6
############################################################
rpm-build d9acb6
# benchmark baseclass
rpm-build d9acb6
############################################################
rpm-build d9acb6
rpm-build d9acb6
class SkippedTest(Exception):
rpm-build d9acb6
    pass
rpm-build d9acb6
rpm-build d9acb6
class TreeBenchMark(object):
rpm-build d9acb6
    atoz = string.ascii_lowercase
rpm-build d9acb6
    repeat100  = range(100)
rpm-build d9acb6
    repeat500  = range(500)
rpm-build d9acb6
    repeat1000 = range(1000)
rpm-build d9acb6
rpm-build d9acb6
    _LIB_NAME_MAP = {
rpm-build d9acb6
        'etree'        : 'lxe',
rpm-build d9acb6
        'ElementTree'  : 'ET',
rpm-build d9acb6
        'cElementTree' : 'cET'
rpm-build d9acb6
        }
rpm-build d9acb6
rpm-build d9acb6
    SEARCH_TAG = "{cdefg}a00001"
rpm-build d9acb6
rpm-build d9acb6
    def __init__(self, etree, etree_parser=None):
rpm-build d9acb6
        self.etree = etree
rpm-build d9acb6
        libname = etree.__name__.split('.')[-1]
rpm-build d9acb6
        self.lib_name = self._LIB_NAME_MAP.get(libname, libname)
rpm-build d9acb6
rpm-build d9acb6
        if libname == 'etree':
rpm-build d9acb6
            deepcopy = copy.deepcopy
rpm-build d9acb6
            def set_property(root, fname):
rpm-build d9acb6
                xml = self._serialize_tree(root)
rpm-build d9acb6
                if etree_parser is not None:
rpm-build d9acb6
                    setattr(self, fname, lambda : etree.XML(xml, etree_parser))
rpm-build d9acb6
                else:
rpm-build d9acb6
                    setattr(self, fname, lambda : deepcopy(root))
rpm-build d9acb6
                setattr(self, fname + '_xml', lambda : xml)
rpm-build d9acb6
                setattr(self, fname + '_children', lambda : root[:])
rpm-build d9acb6
        else:
rpm-build d9acb6
            def set_property(root, fname):
rpm-build d9acb6
                setattr(self, fname, self.et_make_clone_factory(root))
rpm-build d9acb6
                xml = self._serialize_tree(root)
rpm-build d9acb6
                setattr(self, fname + '_xml', lambda : xml)
rpm-build d9acb6
                setattr(self, fname + '_children', lambda : root[:])
rpm-build d9acb6
rpm-build d9acb6
        attribute_list = list(enumerate( [{}, _ATTRIBUTES] ))
rpm-build d9acb6
        text_list = list(enumerate( [None, _TEXT, _UTEXT] ))
rpm-build d9acb6
        build_name = self._tree_builder_name
rpm-build d9acb6
rpm-build d9acb6
        self.setup_times = []
rpm-build d9acb6
        for tree in self._all_trees():
rpm-build d9acb6
            times = []
rpm-build d9acb6
            self.setup_times.append(times)
rpm-build d9acb6
            setup = getattr(self, '_setup_tree%d' % tree)
rpm-build d9acb6
            for an, attributes in attribute_list:
rpm-build d9acb6
                for tn, text in text_list:
rpm-build d9acb6
                    root, t = setup(text, attributes)
rpm-build d9acb6
                    times.append(t)
rpm-build d9acb6
                    set_property(root, build_name(tree, tn, an))
rpm-build d9acb6
rpm-build d9acb6
    def _tree_builder_name(self, tree, tn, an):
rpm-build d9acb6
        return '_root%d_T%d_A%d' % (tree, tn, an)
rpm-build d9acb6
rpm-build d9acb6
    def tree_builder(self, tree, tn, an, serial, children):
rpm-build d9acb6
        name = self._tree_builder_name(tree, tn, an)
rpm-build d9acb6
        if serial:
rpm-build d9acb6
            name += '_xml'
rpm-build d9acb6
        elif children:
rpm-build d9acb6
            name += '_children'
rpm-build d9acb6
        return getattr(self, name)
rpm-build d9acb6
rpm-build d9acb6
    def _serialize_tree(self, root):
rpm-build d9acb6
        return self.etree.tostring(root, encoding='UTF-8')
rpm-build d9acb6
rpm-build d9acb6
    def et_make_clone_factory(self, elem):
rpm-build d9acb6
        def generate_elem(append, elem, level):
rpm-build d9acb6
            var = "e" + str(level)
rpm-build d9acb6
            arg = repr(elem.tag)
rpm-build d9acb6
            if elem.attrib:
rpm-build d9acb6
                arg += ", **%r" % elem.attrib
rpm-build d9acb6
            if level == 1:
rpm-build d9acb6
                append(" e1 = Element(%s)" % arg)
rpm-build d9acb6
            else:
rpm-build d9acb6
                append(" %s = SubElement(e%d, %s)" % (var, level-1, arg))
rpm-build d9acb6
            if elem.text:
rpm-build d9acb6
                append(" %s.text = %r" % (var, elem.text))
rpm-build d9acb6
            if elem.tail:
rpm-build d9acb6
                append(" %s.tail = %r" % (var, elem.tail))
rpm-build d9acb6
            for e in elem:
rpm-build d9acb6
                generate_elem(append, e, level+1)
rpm-build d9acb6
        # generate code for a function that creates a tree
rpm-build d9acb6
        output = ["def element_factory():"]
rpm-build d9acb6
        generate_elem(output.append, elem, 1)
rpm-build d9acb6
        output.append(" return e1")
rpm-build d9acb6
        # setup global function namespace
rpm-build d9acb6
        namespace = {
rpm-build d9acb6
            "Element"    : self.etree.Element,
rpm-build d9acb6
            "SubElement" : self.etree.SubElement
rpm-build d9acb6
            }
rpm-build d9acb6
rpm-build d9acb6
        # create function object
rpm-build d9acb6
        exec_("\n".join(output), namespace)
rpm-build d9acb6
        return namespace["element_factory"]
rpm-build d9acb6
rpm-build d9acb6
    def _all_trees(self):
rpm-build d9acb6
        all_trees = []
rpm-build d9acb6
        for name in dir(self):
rpm-build d9acb6
            if name.startswith('_setup_tree'):
rpm-build d9acb6
                all_trees.append(int(name[11:]))
rpm-build d9acb6
        return all_trees
rpm-build d9acb6
rpm-build d9acb6
    def _setup_tree1(self, text, attributes):
rpm-build d9acb6
        "tree with 26 2nd level and 520 * TREE_FACTOR 3rd level children"
rpm-build d9acb6
        atoz = self.atoz
rpm-build d9acb6
        SubElement = self.etree.SubElement
rpm-build d9acb6
        current_time = time.time
rpm-build d9acb6
        t = current_time()
rpm-build d9acb6
        root = self.etree.Element('{abc}rootnode')
rpm-build d9acb6
        for ch1 in atoz:
rpm-build d9acb6
            el = SubElement(root, "{abc}"+ch1*5, attributes)
rpm-build d9acb6
            el.text = text
rpm-build d9acb6
            for ch2 in atoz:
rpm-build d9acb6
                tag = "{cdefg}%s00001" % ch2
rpm-build d9acb6
                for i in range(20 * TREE_FACTOR):
rpm-build d9acb6
                    SubElement(el, tag).tail = text
rpm-build d9acb6
        t = current_time() - t
rpm-build d9acb6
        return (root, t)
rpm-build d9acb6
rpm-build d9acb6
    def _setup_tree2(self, text, attributes):
rpm-build d9acb6
        "tree with 520 * TREE_FACTOR 2nd level and 26 3rd level children"
rpm-build d9acb6
        atoz = self.atoz
rpm-build d9acb6
        SubElement = self.etree.SubElement
rpm-build d9acb6
        current_time = time.time
rpm-build d9acb6
        t = current_time()
rpm-build d9acb6
        root = self.etree.Element('{abc}rootnode')
rpm-build d9acb6
        for ch1 in atoz:
rpm-build d9acb6
            for i in range(20 * TREE_FACTOR):
rpm-build d9acb6
                el = SubElement(root, "{abc}"+ch1*5, attributes)
rpm-build d9acb6
                el.text = text
rpm-build d9acb6
                for ch2 in atoz:
rpm-build d9acb6
                    SubElement(el, "{cdefg}%s00001" % ch2).tail = text
rpm-build d9acb6
        t = current_time() - t
rpm-build d9acb6
        return (root, t)
rpm-build d9acb6
rpm-build d9acb6
    def _setup_tree3(self, text, attributes):
rpm-build d9acb6
        "tree of depth 8 + TREE_FACTOR with 3 children per node"
rpm-build d9acb6
        SubElement = self.etree.SubElement
rpm-build d9acb6
        current_time = time.time
rpm-build d9acb6
        t = current_time()
rpm-build d9acb6
        root = self.etree.Element('{abc}rootnode')
rpm-build d9acb6
        children = [root]
rpm-build d9acb6
        for i in range(6 + TREE_FACTOR):
rpm-build d9acb6
            children = [ SubElement(c, "{cdefg}a%05d" % (i%8), attributes)
rpm-build d9acb6
                         for i,c in enumerate(chain(children, children, children)) ]
rpm-build d9acb6
        for child in children:
rpm-build d9acb6
            child.text = text
rpm-build d9acb6
            child.tail = text
rpm-build d9acb6
        t = current_time() - t
rpm-build d9acb6
        return (root, t)
rpm-build d9acb6
rpm-build d9acb6
    def _setup_tree4(self, text, attributes):
rpm-build d9acb6
        "small tree with 26 2nd level and 2 3rd level children"
rpm-build d9acb6
        SubElement = self.etree.SubElement
rpm-build d9acb6
        current_time = time.time
rpm-build d9acb6
        t = current_time()
rpm-build d9acb6
        root = self.etree.Element('{abc}rootnode')
rpm-build d9acb6
        for ch1 in self.atoz:
rpm-build d9acb6
            el = SubElement(root, "{abc}"+ch1*5, attributes)
rpm-build d9acb6
            el.text = text
rpm-build d9acb6
            SubElement(el, "{cdefg}a00001", attributes).tail = text
rpm-build d9acb6
            SubElement(el, "{cdefg}z00000", attributes).tail = text
rpm-build d9acb6
        t = current_time() - t
rpm-build d9acb6
        return (root, t)
rpm-build d9acb6
rpm-build d9acb6
    def benchmarks(self):
rpm-build d9acb6
        """Returns a list of all benchmarks.
rpm-build d9acb6
rpm-build d9acb6
        A benchmark is a tuple containing a method name and a list of tree
rpm-build d9acb6
        numbers.  Trees are prepared by the setup function.
rpm-build d9acb6
        """
rpm-build d9acb6
        all_trees = self._all_trees()
rpm-build d9acb6
        benchmarks = []
rpm-build d9acb6
        for name in dir(self):
rpm-build d9acb6
            if not name.startswith('bench_'):
rpm-build d9acb6
                continue
rpm-build d9acb6
            method = getattr(self, name)
rpm-build d9acb6
            if hasattr(method, 'LIBS') and self.lib_name not in method.LIBS:
rpm-build d9acb6
                method_call = None
rpm-build d9acb6
            else:
rpm-build d9acb6
                method_call = method
rpm-build d9acb6
            if method.__doc__:
rpm-build d9acb6
                tree_sets = method.__doc__.split()
rpm-build d9acb6
            else:
rpm-build d9acb6
                tree_sets = ()
rpm-build d9acb6
            if tree_sets:
rpm-build d9acb6
                tree_tuples = [list(map(int, tree_set.split(',')))
rpm-build d9acb6
                               for tree_set in tree_sets]
rpm-build d9acb6
            else:
rpm-build d9acb6
                try:
rpm-build d9acb6
                    arg_count = method.func_code.co_argcount - 1
rpm-build d9acb6
                except AttributeError:
rpm-build d9acb6
                    try:
rpm-build d9acb6
                        arg_count = method.__code__.co_argcount - 1
rpm-build d9acb6
                    except AttributeError:
rpm-build d9acb6
                        arg_count = 1
rpm-build d9acb6
                tree_tuples = self._permutations(all_trees, arg_count)
rpm-build d9acb6
rpm-build d9acb6
            serialized = getattr(method, 'STRING',   False)
rpm-build d9acb6
            children   = getattr(method, 'CHILDREN', False)
rpm-build d9acb6
            no_change  = getattr(method, 'NO_CHANGE', False)
rpm-build d9acb6
rpm-build d9acb6
            for tree_tuple in tree_tuples:
rpm-build d9acb6
                for tn in sorted(getattr(method, 'TEXT', (0,))):
rpm-build d9acb6
                    for an in sorted(getattr(method, 'ATTRIBUTES', (0,))):
rpm-build d9acb6
                        benchmarks.append((name, method_call, tree_tuple,
rpm-build d9acb6
                                           tn, an, serialized, children,
rpm-build d9acb6
                                           no_change))
rpm-build d9acb6
rpm-build d9acb6
        return benchmarks
rpm-build d9acb6
rpm-build d9acb6
    def _permutations(self, seq, count):
rpm-build d9acb6
        def _permutations(prefix, remainder, count):
rpm-build d9acb6
            if count == 0:
rpm-build d9acb6
                return [ prefix[:] ]
rpm-build d9acb6
            count -= 1
rpm-build d9acb6
            perms = []
rpm-build d9acb6
            prefix.append(None)
rpm-build d9acb6
            for pos, el in enumerate(remainder):
rpm-build d9acb6
                new_remainder = remainder[:pos] + remainder[pos+1:]
rpm-build d9acb6
                prefix[-1] = el
rpm-build d9acb6
                perms.extend( _permutations(prefix, new_remainder, count) )
rpm-build d9acb6
            prefix.pop()
rpm-build d9acb6
            return perms
rpm-build d9acb6
        return _permutations([], seq, count)
rpm-build d9acb6
rpm-build d9acb6
############################################################
rpm-build d9acb6
# Prepare and run benchmark suites
rpm-build d9acb6
############################################################
rpm-build d9acb6
rpm-build d9acb6
def buildSuites(benchmark_class, etrees, selected):
rpm-build d9acb6
    benchmark_suites = list(map(benchmark_class, etrees))
rpm-build d9acb6
rpm-build d9acb6
    # sorted by name and tree tuple
rpm-build d9acb6
    benchmarks = [ sorted(b.benchmarks()) for b in benchmark_suites ]
rpm-build d9acb6
rpm-build d9acb6
    selected = [ re.compile(r).search for r in selected ]
rpm-build d9acb6
rpm-build d9acb6
    if selected:
rpm-build d9acb6
        benchmarks = [ [ b for b in bs
rpm-build d9acb6
                         if [ match for match in selected
rpm-build d9acb6
                              if match(b[0]) ] ]
rpm-build d9acb6
                       for bs in benchmarks ]
rpm-build d9acb6
rpm-build d9acb6
    return (benchmark_suites, benchmarks)
rpm-build d9acb6
rpm-build d9acb6
def build_treeset_name(trees, tn, an, serialized, children):
rpm-build d9acb6
    text = {0:'-', 1:'S', 2:'U'}[tn]
rpm-build d9acb6
    attr = {0:'-', 1:'A'}[an]
rpm-build d9acb6
    ser  = {True:'X', False:'T'}[serialized]
rpm-build d9acb6
    chd  = {True:'C', False:'R'}[children]
rpm-build d9acb6
    return "%s%s%s%s T%s" % (text, attr, ser, chd, ',T'.join(map(str, trees))[:6])
rpm-build d9acb6
rpm-build d9acb6
def printSetupTimes(benchmark_suites):
rpm-build d9acb6
    print("Setup times for trees in seconds:")
rpm-build d9acb6
    for b in benchmark_suites:
rpm-build d9acb6
        sys.stdout.write("%-3s:     " % b.lib_name)
rpm-build d9acb6
        for an in (0,1):
rpm-build d9acb6
            for tn in (0,1,2):
rpm-build d9acb6
                sys.stdout.write('  %s   ' %
rpm-build d9acb6
                    build_treeset_name((), tn, an, False, False)[:2])
rpm-build d9acb6
        print('')
rpm-build d9acb6
        for i, tree_times in enumerate(b.setup_times):
rpm-build d9acb6
            print("     T%d: %s" % (i+1, ' '.join("%6.4f" % t for t in tree_times)))
rpm-build d9acb6
    print('')
rpm-build d9acb6
rpm-build d9acb6
def runBench(suite, method_name, method_call, tree_set, tn, an,
rpm-build d9acb6
             serial, children, no_change):
rpm-build d9acb6
    if method_call is None:
rpm-build d9acb6
        raise SkippedTest
rpm-build d9acb6
rpm-build d9acb6
    current_time = time.time
rpm-build d9acb6
    call_repeat = range(10)
rpm-build d9acb6
rpm-build d9acb6
    tree_builders = [ suite.tree_builder(tree, tn, an, serial, children)
rpm-build d9acb6
                      for tree in tree_set ]
rpm-build d9acb6
rpm-build d9acb6
    rebuild_trees = not no_change and not serial
rpm-build d9acb6
rpm-build d9acb6
    args = tuple([ build() for build in tree_builders ])
rpm-build d9acb6
    method_call(*args) # run once to skip setup overhead
rpm-build d9acb6
rpm-build d9acb6
    times = []
rpm-build d9acb6
    for i in range(3):
rpm-build d9acb6
        gc.collect()
rpm-build d9acb6
        gc.disable()
rpm-build d9acb6
        t = -1
rpm-build d9acb6
        for i in call_repeat:
rpm-build d9acb6
            if rebuild_trees:
rpm-build d9acb6
                args = [ build() for build in tree_builders ]
rpm-build d9acb6
            t_one_call = current_time()
rpm-build d9acb6
            method_call(*args)
rpm-build d9acb6
            t_one_call = current_time() - t_one_call
rpm-build d9acb6
            if t < 0:
rpm-build d9acb6
                t = t_one_call
rpm-build d9acb6
            else:
rpm-build d9acb6
                t = min(t, t_one_call)
rpm-build d9acb6
        times.append(1000.0 * t)
rpm-build d9acb6
        gc.enable()
rpm-build d9acb6
        if rebuild_trees:
rpm-build d9acb6
            args = ()
rpm-build d9acb6
    args = ()
rpm-build d9acb6
    gc.collect()
rpm-build d9acb6
    return times
rpm-build d9acb6
rpm-build d9acb6
rpm-build d9acb6
def runBenchmarks(benchmark_suites, benchmarks):
rpm-build d9acb6
    for bench_calls in izip(*benchmarks):
rpm-build d9acb6
        for lib, (bench, benchmark_setup) in enumerate(izip(benchmark_suites, bench_calls)):
rpm-build d9acb6
            bench_name = benchmark_setup[0]
rpm-build d9acb6
            tree_set_name = build_treeset_name(*benchmark_setup[-6:-1])
rpm-build d9acb6
            sys.stdout.write("%-3s: %-28s (%-10s) " % (
rpm-build d9acb6
                bench.lib_name, bench_name[6:34], tree_set_name))
rpm-build d9acb6
            sys.stdout.flush()
rpm-build d9acb6
rpm-build d9acb6
            try:
rpm-build d9acb6
                result = runBench(bench, *benchmark_setup)
rpm-build d9acb6
            except SkippedTest:
rpm-build d9acb6
                print("skipped")
rpm-build d9acb6
            except KeyboardInterrupt:
rpm-build d9acb6
                print("interrupted by user")
rpm-build d9acb6
                sys.exit(1)
rpm-build d9acb6
            except Exception:
rpm-build d9acb6
                exc_type, exc_value = sys.exc_info()[:2]
rpm-build d9acb6
                print("failed: %s: %s" % (exc_type.__name__, exc_value))
rpm-build d9acb6
                exc_type = exc_value = None
rpm-build d9acb6
            else:
rpm-build d9acb6
                print("%9.4f msec/pass, best of (%s)" % (
rpm-build d9acb6
                      min(result), ' '.join("%9.4f" % t for t in result)))
rpm-build d9acb6
rpm-build d9acb6
        if len(benchmark_suites) > 1:
rpm-build d9acb6
            print('')  # empty line between different benchmarks
rpm-build d9acb6
rpm-build d9acb6
############################################################
rpm-build d9acb6
# Main program
rpm-build d9acb6
############################################################
rpm-build d9acb6
rpm-build d9acb6
def main(benchmark_class):
rpm-build d9acb6
    import_lxml = True
rpm-build d9acb6
    callgrind_zero = False
rpm-build d9acb6
    if len(sys.argv) > 1:
rpm-build d9acb6
        try:
rpm-build d9acb6
            sys.argv.remove('-i')
rpm-build d9acb6
            # run benchmark 'inplace'
rpm-build d9acb6
            sys.path.insert(0, 'src')
rpm-build d9acb6
        except ValueError:
rpm-build d9acb6
            pass
rpm-build d9acb6
rpm-build d9acb6
        try:
rpm-build d9acb6
            sys.argv.remove('-nolxml')
rpm-build d9acb6
            # run without lxml
rpm-build d9acb6
            import_lxml = False
rpm-build d9acb6
        except ValueError:
rpm-build d9acb6
            pass
rpm-build d9acb6
rpm-build d9acb6
        try:
rpm-build d9acb6
            sys.argv.remove('-z')
rpm-build d9acb6
            # reset callgrind after tree setup
rpm-build d9acb6
            callgrind_zero = True
rpm-build d9acb6
        except ValueError:
rpm-build d9acb6
            pass
rpm-build d9acb6
rpm-build d9acb6
        initArgs(sys.argv)
rpm-build d9acb6
rpm-build d9acb6
    _etrees = []
rpm-build d9acb6
    if import_lxml:
rpm-build d9acb6
        from lxml import etree
rpm-build d9acb6
        _etrees.append(etree)
rpm-build d9acb6
rpm-build d9acb6
        try:
rpm-build d9acb6
            sys.argv.remove('-fel')
rpm-build d9acb6
        except ValueError:
rpm-build d9acb6
            pass
rpm-build d9acb6
        else:
rpm-build d9acb6
            # use fast element creation in lxml.etree
rpm-build d9acb6
            etree.set_element_class_lookup(
rpm-build d9acb6
                etree.ElementDefaultClassLookup())
rpm-build d9acb6
rpm-build d9acb6
    if len(sys.argv) > 1:
rpm-build d9acb6
        if '-a' in sys.argv or '-c' in sys.argv:
rpm-build d9acb6
            # 'all' or 'C-implementations' ?
rpm-build d9acb6
            try:
rpm-build d9acb6
                sys.argv.remove('-c')
rpm-build d9acb6
            except ValueError:
rpm-build d9acb6
                pass
rpm-build d9acb6
            try:
rpm-build d9acb6
                import cElementTree as cET
rpm-build d9acb6
                _etrees.append(cET)
rpm-build d9acb6
            except ImportError:
rpm-build d9acb6
                try:
rpm-build d9acb6
                    import xml.etree.cElementTree as cET
rpm-build d9acb6
                    _etrees.append(cET)
rpm-build d9acb6
                except ImportError:
rpm-build d9acb6
                    pass
rpm-build d9acb6
rpm-build d9acb6
        try:
rpm-build d9acb6
            # 'all' ?
rpm-build d9acb6
            sys.argv.remove('-a')
rpm-build d9acb6
        except ValueError:
rpm-build d9acb6
            pass
rpm-build d9acb6
        else:
rpm-build d9acb6
            try:
rpm-build d9acb6
                from elementtree import ElementTree as ET
rpm-build d9acb6
                _etrees.append(ET)
rpm-build d9acb6
            except ImportError:
rpm-build d9acb6
                try:
rpm-build d9acb6
                    from xml.etree import ElementTree as ET
rpm-build d9acb6
                    _etrees.append(ET)
rpm-build d9acb6
                except ImportError:
rpm-build d9acb6
                    pass
rpm-build d9acb6
rpm-build d9acb6
    if not _etrees:
rpm-build d9acb6
        print("No library to test. Exiting.")
rpm-build d9acb6
        sys.exit(1)
rpm-build d9acb6
rpm-build d9acb6
    print("Preparing test suites and trees ...")
rpm-build d9acb6
    selected = set( sys.argv[1:] )
rpm-build d9acb6
    benchmark_suites, benchmarks = \
rpm-build d9acb6
                      buildSuites(benchmark_class, _etrees, selected)
rpm-build d9acb6
rpm-build d9acb6
    print("Running benchmark on", ', '.join(b.lib_name
rpm-build d9acb6
                                            for b in benchmark_suites))
rpm-build d9acb6
    print('')
rpm-build d9acb6
rpm-build d9acb6
    printSetupTimes(benchmark_suites)
rpm-build d9acb6
rpm-build d9acb6
    if callgrind_zero:
rpm-build d9acb6
        cmd = open("callgrind.cmd", 'w')
rpm-build d9acb6
        cmd.write('+Instrumentation\n')
rpm-build d9acb6
        cmd.write('Zero\n')
rpm-build d9acb6
        cmd.close()
rpm-build d9acb6
rpm-build d9acb6
    runBenchmarks(benchmark_suites, benchmarks)