|
| 1 | +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. |
| 2 | +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 3 | +# |
| 4 | +# The Universal Permissive License (UPL), Version 1.0 |
| 5 | +# |
| 6 | +# Subject to the condition set forth below, permission is hereby granted to any |
| 7 | +# person obtaining a copy of this software, associated documentation and/or |
| 8 | +# data (collectively the "Software"), free of charge and under any and all |
| 9 | +# copyright rights in the Software, and any and all patent rights owned or |
| 10 | +# freely licensable by each licensor hereunder covering either (i) the |
| 11 | +# unmodified Software as contributed to or provided by such licensor, or (ii) |
| 12 | +# the Larger Works (as defined below), to deal in both |
| 13 | +# |
| 14 | +# (a) the Software, and |
| 15 | +# |
| 16 | +# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if |
| 17 | +# one is included with the Software each a "Larger Work" to which the Software |
| 18 | +# is contributed by such licensors), |
| 19 | +# |
| 20 | +# without restriction, including without limitation the rights to copy, create |
| 21 | +# derivative works of, display, perform, and distribute the Software and make, |
| 22 | +# use, sell, offer for sale, import, export, have made, and have sold the |
| 23 | +# Software and the Larger Work(s), and to sublicense the foregoing rights on |
| 24 | +# either these or other terms. |
| 25 | +# |
| 26 | +# This license is subject to the following condition: |
| 27 | +# |
| 28 | +# The above copyright notice and either this complete permission notice or at a |
| 29 | +# minimum a reference to the UPL must be included in all copies or substantial |
| 30 | +# portions of the Software. |
| 31 | +# |
| 32 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 33 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 34 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 35 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 36 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 37 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 38 | +# SOFTWARE. |
| 39 | + |
| 40 | +import _io |
| 41 | +import os |
| 42 | +import sys |
| 43 | +from time import time |
| 44 | + |
| 45 | +_HRULE = '-'.join(['' for i in range(80)]) |
| 46 | +ATTR_BENCHMARK = '__benchmark__' |
| 47 | +ATTR_PROCESS_ARGS = '__process_args__' |
| 48 | + |
| 49 | + |
| 50 | +def _as_int(value): |
| 51 | + if isinstance(value, (list, tuple)): |
| 52 | + value = value[0] |
| 53 | + |
| 54 | + if not isinstance(value, int): |
| 55 | + return int(value) |
| 56 | + return value |
| 57 | + |
| 58 | + |
| 59 | +class BenchRunner(object): |
| 60 | + def __init__(self, bench_file, bench_args=None, iterations=1, warmup=0): |
| 61 | + if bench_args is None: |
| 62 | + bench_args = [] |
| 63 | + self.bench_module = BenchRunner.get_bench_module(bench_file) |
| 64 | + self.bench_args = bench_args |
| 65 | + self.iterations = _as_int(iterations) |
| 66 | + assert isinstance(self.iterations, int) |
| 67 | + self.warmup = _as_int(warmup) |
| 68 | + assert isinstance(self.warmup, int) |
| 69 | + |
| 70 | + @staticmethod |
| 71 | + def get_bench_module(bench_file): |
| 72 | + name = bench_file.rpartition("/")[2].partition(".")[0].replace('.py', '') |
| 73 | + directory = bench_file.rpartition("/")[0] |
| 74 | + pkg = [] |
| 75 | + while any(f.endswith("__init__.py") for f in os.listdir(directory)): |
| 76 | + directory, slash, postfix = directory.rpartition("/") |
| 77 | + pkg.insert(0, postfix) |
| 78 | + |
| 79 | + if pkg: |
| 80 | + sys.path.insert(0, directory) |
| 81 | + bench_module = __import__(".".join(pkg + [name])) |
| 82 | + for p in pkg[1:]: |
| 83 | + bench_module = getattr(bench_module, p) |
| 84 | + bench_module = getattr(bench_module, name) |
| 85 | + return bench_module |
| 86 | + |
| 87 | + else: |
| 88 | + bench_module = type(sys)(name, bench_file) |
| 89 | + with _io.FileIO(bench_file, "r") as f: |
| 90 | + bench_module.__file__ = bench_file |
| 91 | + exec(compile(f.readall(), bench_file, "exec"), bench_module.__dict__) |
| 92 | + return bench_module |
| 93 | + |
| 94 | + def _get_attr(self, attr_name): |
| 95 | + if hasattr(self.bench_module, attr_name): |
| 96 | + return getattr(self.bench_module, attr_name) |
| 97 | + |
| 98 | + def _call_attr(self, attr_name, *args): |
| 99 | + attr = self._get_attr(attr_name) |
| 100 | + if attr and hasattr(attr, '__call__'): |
| 101 | + return attr(*args) |
| 102 | + |
| 103 | + def run(self): |
| 104 | + print(_HRULE) |
| 105 | + print("### %s, %s warmup iterations, %s bench iterations " % (self.bench_module.__name__, self.warmup, self.iterations)) |
| 106 | + |
| 107 | + # process the args if the processor function is defined |
| 108 | + args = self._call_attr(ATTR_PROCESS_ARGS, *self.bench_args) |
| 109 | + if args is None: |
| 110 | + # default args processor considers all args as ints |
| 111 | + args = list(map(int, self.bench_args)) |
| 112 | + |
| 113 | + print("### args = %s" % args) |
| 114 | + print(_HRULE) |
| 115 | + |
| 116 | + bench_func = self._get_attr(ATTR_BENCHMARK) |
| 117 | + if bench_func and hasattr(bench_func, '__call__'): |
| 118 | + if self.warmup: |
| 119 | + print("### warming up for %s iterations ... " % self.warmup) |
| 120 | + for _ in range(self.warmup): |
| 121 | + bench_func(*args) |
| 122 | + |
| 123 | + for iteration in range(self.iterations): |
| 124 | + start = time() |
| 125 | + bench_func(*args) |
| 126 | + duration = "%.3f" % (time() - start) |
| 127 | + print("### iteration=%s, name=%s, duration=%s" % (iteration, self.bench_module.__name__, duration)) |
| 128 | + |
| 129 | + |
| 130 | +def run_benchmark(prog, args): |
| 131 | + warmup = 0 |
| 132 | + iterations = 1 |
| 133 | + bench_file = None |
| 134 | + bench_args = [] |
| 135 | + |
| 136 | + i = 0 |
| 137 | + while i < len(args): |
| 138 | + arg = args[i] |
| 139 | + if arg == '-i': |
| 140 | + i += 1 |
| 141 | + iterations = _as_int(args[i]) |
| 142 | + elif arg.startswith("--iterations"): |
| 143 | + iterations = _as_int(arg.split("=")[1]) |
| 144 | + elif arg == '-w': |
| 145 | + i += 1 |
| 146 | + warmup = _as_int(args[i]) |
| 147 | + elif arg.startswith("--warmup"): |
| 148 | + warmup = _as_int(arg.split("=")[1]) |
| 149 | + elif bench_file is None: |
| 150 | + bench_file = arg |
| 151 | + else: |
| 152 | + bench_args.append(arg) |
| 153 | + i += 1 |
| 154 | + |
| 155 | + BenchRunner(bench_file, bench_args=bench_args, iterations=iterations, warmup=warmup).run() |
| 156 | + |
| 157 | + |
| 158 | +if __name__ == '__main__': |
| 159 | + run_benchmark(sys.argv[0], sys.argv[1:]) |
0 commit comments