xref: /aosp_15_r20/external/google-fruit/extras/benchmark/run_benchmarks.py (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
1*a65addddSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*a65addddSAndroid Build Coastguard Worker# Copyright 2016 Google Inc. All Rights Reserved.
3*a65addddSAndroid Build Coastguard Worker#
4*a65addddSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker#
8*a65addddSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker#
10*a65addddSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS-IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker# limitations under the License.
15*a65addddSAndroid Build Coastguard Worker
16*a65addddSAndroid Build Coastguard Workerimport argparse
17*a65addddSAndroid Build Coastguard Workerimport re
18*a65addddSAndroid Build Coastguard Workerimport textwrap
19*a65addddSAndroid Build Coastguard Workerfrom collections import defaultdict
20*a65addddSAndroid Build Coastguard Workerfrom timeit import default_timer as timer
21*a65addddSAndroid Build Coastguard Workerimport tempfile
22*a65addddSAndroid Build Coastguard Workerimport os
23*a65addddSAndroid Build Coastguard Workerimport shutil
24*a65addddSAndroid Build Coastguard Workerimport itertools
25*a65addddSAndroid Build Coastguard Workerimport traceback
26*a65addddSAndroid Build Coastguard Workerfrom typing import Dict, List, Tuple, Optional, Any, TypeVar, Callable, Iterable
27*a65addddSAndroid Build Coastguard Worker
28*a65addddSAndroid Build Coastguard Workerimport numpy
29*a65addddSAndroid Build Coastguard Workerimport subprocess
30*a65addddSAndroid Build Coastguard Workerimport yaml
31*a65addddSAndroid Build Coastguard Workerfrom numpy import floor, log10
32*a65addddSAndroid Build Coastguard Workerimport scipy
33*a65addddSAndroid Build Coastguard Workerimport multiprocessing
34*a65addddSAndroid Build Coastguard Workerimport json
35*a65addddSAndroid Build Coastguard Workerimport statsmodels.stats.api as stats
36*a65addddSAndroid Build Coastguard Workerfrom generate_benchmark import generate_benchmark
37*a65addddSAndroid Build Coastguard Workerimport git
38*a65addddSAndroid Build Coastguard Workerfrom functools import lru_cache as memoize
39*a65addddSAndroid Build Coastguard Worker
40*a65addddSAndroid Build Coastguard Workerclass CommandFailedException(Exception):
41*a65addddSAndroid Build Coastguard Worker    def __init__(self, command: List[str], stdout: str, stderr: str, error_code: str):
42*a65addddSAndroid Build Coastguard Worker        self.command = command
43*a65addddSAndroid Build Coastguard Worker        self.stdout = stdout
44*a65addddSAndroid Build Coastguard Worker        self.stderr = stderr
45*a65addddSAndroid Build Coastguard Worker        self.error_code = error_code
46*a65addddSAndroid Build Coastguard Worker
47*a65addddSAndroid Build Coastguard Worker    def __str__(self):
48*a65addddSAndroid Build Coastguard Worker        return textwrap.dedent('''\
49*a65addddSAndroid Build Coastguard Worker        Ran command: {command}
50*a65addddSAndroid Build Coastguard Worker        Exit code {error_code}
51*a65addddSAndroid Build Coastguard Worker        Stdout:
52*a65addddSAndroid Build Coastguard Worker        {stdout}
53*a65addddSAndroid Build Coastguard Worker
54*a65addddSAndroid Build Coastguard Worker        Stderr:
55*a65addddSAndroid Build Coastguard Worker        {stderr}
56*a65addddSAndroid Build Coastguard Worker        ''').format(command=self.command, error_code=self.error_code, stdout=self.stdout, stderr=self.stderr)
57*a65addddSAndroid Build Coastguard Worker
58*a65addddSAndroid Build Coastguard Workerdef run_command(executable: str, args: List[Any]=[], cwd: str=None, env: Dict[str, str]=None) -> Tuple[str, str]:
59*a65addddSAndroid Build Coastguard Worker    args = [str(arg) for arg in args]
60*a65addddSAndroid Build Coastguard Worker    command = [executable] + args
61*a65addddSAndroid Build Coastguard Worker    try:
62*a65addddSAndroid Build Coastguard Worker        p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, cwd=cwd,
63*a65addddSAndroid Build Coastguard Worker                             env=env)
64*a65addddSAndroid Build Coastguard Worker        (stdout, stderr) = p.communicate()
65*a65addddSAndroid Build Coastguard Worker    except Exception as e:
66*a65addddSAndroid Build Coastguard Worker        raise Exception("While executing: %s" % command)
67*a65addddSAndroid Build Coastguard Worker    if p.returncode != 0:
68*a65addddSAndroid Build Coastguard Worker        raise CommandFailedException(command, stdout, stderr, p.returncode)
69*a65addddSAndroid Build Coastguard Worker    return (stdout, stderr)
70*a65addddSAndroid Build Coastguard Worker
71*a65addddSAndroid Build Coastguard Workercompile_flags = ['-O2', '-DNDEBUG']
72*a65addddSAndroid Build Coastguard Worker
73*a65addddSAndroid Build Coastguard Workermake_args = ['-j', multiprocessing.cpu_count() + 1]
74*a65addddSAndroid Build Coastguard Worker
75*a65addddSAndroid Build Coastguard Workerdef parse_results(result_lines: List[str]) -> Dict[str, float]:
76*a65addddSAndroid Build Coastguard Worker    """
77*a65addddSAndroid Build Coastguard Worker     Parses results from the format:
78*a65addddSAndroid Build Coastguard Worker     ['Dimension name1        = 123',
79*a65addddSAndroid Build Coastguard Worker      'Long dimension name2   = 23.45']
80*a65addddSAndroid Build Coastguard Worker
81*a65addddSAndroid Build Coastguard Worker     Into a dict {'Dimension name1': 123.0, 'Dimension name2': 23.45}
82*a65addddSAndroid Build Coastguard Worker    """
83*a65addddSAndroid Build Coastguard Worker    result_dict = dict()
84*a65addddSAndroid Build Coastguard Worker    for line in result_lines:
85*a65addddSAndroid Build Coastguard Worker        line_splits = line.split('=')
86*a65addddSAndroid Build Coastguard Worker        metric = line_splits[0].strip()
87*a65addddSAndroid Build Coastguard Worker        value = float(line_splits[1].strip())
88*a65addddSAndroid Build Coastguard Worker        result_dict[metric] = value
89*a65addddSAndroid Build Coastguard Worker    return result_dict
90*a65addddSAndroid Build Coastguard Worker
91*a65addddSAndroid Build Coastguard Worker
92*a65addddSAndroid Build Coastguard Worker# We memoize the result since this might be called repeatedly and it's somewhat expensive.
93*a65addddSAndroid Build Coastguard Worker@memoize(maxsize=None)
94*a65addddSAndroid Build Coastguard Workerdef determine_compiler_name(compiler_executable_name: str) -> str:
95*a65addddSAndroid Build Coastguard Worker    tmpdir = tempfile.gettempdir() + '/fruit-determine-compiler-version-dir'
96*a65addddSAndroid Build Coastguard Worker    ensure_empty_dir(tmpdir)
97*a65addddSAndroid Build Coastguard Worker    with open(tmpdir + '/CMakeLists.txt', 'w') as file:
98*a65addddSAndroid Build Coastguard Worker        file.write('message("@@@${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}@@@")\n')
99*a65addddSAndroid Build Coastguard Worker    modified_env = os.environ.copy()
100*a65addddSAndroid Build Coastguard Worker    modified_env['CXX'] = compiler_executable_name
101*a65addddSAndroid Build Coastguard Worker    # By converting to a list, we force all output to be read (so the command execution is guaranteed to be complete after this line).
102*a65addddSAndroid Build Coastguard Worker    # Otherwise, subsequent calls to determine_compiler_name might have trouble deleting the temporary directory because the cmake
103*a65addddSAndroid Build Coastguard Worker    # process is still writing files in there.
104*a65addddSAndroid Build Coastguard Worker    _, stderr = run_command('cmake', args=['.'], cwd=tmpdir, env=modified_env)
105*a65addddSAndroid Build Coastguard Worker    cmake_output = stderr.splitlines()
106*a65addddSAndroid Build Coastguard Worker    for line in cmake_output:
107*a65addddSAndroid Build Coastguard Worker        re_result = re.search('@@@(.*)@@@', line)
108*a65addddSAndroid Build Coastguard Worker        if re_result:
109*a65addddSAndroid Build Coastguard Worker            pretty_name = re_result.group(1)
110*a65addddSAndroid Build Coastguard Worker            # CMake calls GCC 'GNU', change it into 'GCC'.
111*a65addddSAndroid Build Coastguard Worker            return pretty_name.replace('GNU ', 'GCC ')
112*a65addddSAndroid Build Coastguard Worker    raise Exception('Unable to determine compiler. CMake output was: \n', cmake_output)
113*a65addddSAndroid Build Coastguard Worker
114*a65addddSAndroid Build Coastguard Worker
115*a65addddSAndroid Build Coastguard Worker# Returns a pair (sha256_hash, version_name), where version_name will be None if no version tag was found at HEAD.
116*a65addddSAndroid Build Coastguard Worker@memoize(maxsize=None)
117*a65addddSAndroid Build Coastguard Workerdef git_repo_info(repo_path: str) -> Tuple[str, str]:
118*a65addddSAndroid Build Coastguard Worker    repo = git.Repo(repo_path)
119*a65addddSAndroid Build Coastguard Worker    head_tags = [tag.name for tag in repo.tags if tag.commit == repo.head.commit and re.match('v[0-9].*', tag.name)]
120*a65addddSAndroid Build Coastguard Worker    if head_tags == []:
121*a65addddSAndroid Build Coastguard Worker        head_tag = None
122*a65addddSAndroid Build Coastguard Worker    else:
123*a65addddSAndroid Build Coastguard Worker        # There should be only 1 version at any given commit.
124*a65addddSAndroid Build Coastguard Worker        [head_tag] = head_tags
125*a65addddSAndroid Build Coastguard Worker        # Remove the 'v' prefix.
126*a65addddSAndroid Build Coastguard Worker        head_tag = head_tag[1:]
127*a65addddSAndroid Build Coastguard Worker    return (repo.head.commit.hexsha, head_tag)
128*a65addddSAndroid Build Coastguard Worker
129*a65addddSAndroid Build Coastguard Worker
130*a65addddSAndroid Build Coastguard Worker# Some benchmark parameters, e.g. 'compiler_name' are synthesized automatically from other dimensions (e.g. 'compiler' dimension) or from the environment.
131*a65addddSAndroid Build Coastguard Worker# We put the compiler name/version in the results because the same 'compiler' value might refer to different compiler versions
132*a65addddSAndroid Build Coastguard Worker# (e.g. if GCC 6.0.0 is installed when benchmarks are run, then it's updated to GCC 6.0.1 and finally the results are formatted, we
133*a65addddSAndroid Build Coastguard Worker# want the formatted results to say "GCC 6.0.0" instead of "GCC 6.0.1").
134*a65addddSAndroid Build Coastguard Workerdef add_synthetic_benchmark_parameters(original_benchmark_parameters: Dict[str, Any], path_to_code_under_test: Optional[str]):
135*a65addddSAndroid Build Coastguard Worker    benchmark_params = original_benchmark_parameters.copy()
136*a65addddSAndroid Build Coastguard Worker    benchmark_params['compiler_name'] = determine_compiler_name(original_benchmark_parameters['compiler'])
137*a65addddSAndroid Build Coastguard Worker    if path_to_code_under_test is not None:
138*a65addddSAndroid Build Coastguard Worker        sha256_hash, version_name = git_repo_info(path_to_code_under_test)
139*a65addddSAndroid Build Coastguard Worker        benchmark_params['di_library_git_commit_hash'] = sha256_hash
140*a65addddSAndroid Build Coastguard Worker        if version_name is not None:
141*a65addddSAndroid Build Coastguard Worker            benchmark_params['di_library_version_name'] = version_name
142*a65addddSAndroid Build Coastguard Worker    return benchmark_params
143*a65addddSAndroid Build Coastguard Worker
144*a65addddSAndroid Build Coastguard Worker
145*a65addddSAndroid Build Coastguard Workerclass Benchmark:
146*a65addddSAndroid Build Coastguard Worker    def prepare(self) -> None: ...
147*a65addddSAndroid Build Coastguard Worker    def run(self) -> Dict[str, float]: ...
148*a65addddSAndroid Build Coastguard Worker    def describe(self) -> str: ...
149*a65addddSAndroid Build Coastguard Worker
150*a65addddSAndroid Build Coastguard Workerclass SimpleNewDeleteRunTimeBenchmark(Benchmark):
151*a65addddSAndroid Build Coastguard Worker    def __init__(self, benchmark_definition: Dict[str, Any], fruit_benchmark_sources_dir: str):
152*a65addddSAndroid Build Coastguard Worker        self.benchmark_definition = add_synthetic_benchmark_parameters(benchmark_definition, path_to_code_under_test=None)
153*a65addddSAndroid Build Coastguard Worker        self.fruit_benchmark_sources_dir = fruit_benchmark_sources_dir
154*a65addddSAndroid Build Coastguard Worker
155*a65addddSAndroid Build Coastguard Worker    def prepare(self):
156*a65addddSAndroid Build Coastguard Worker        cxx_std = self.benchmark_definition['cxx_std']
157*a65addddSAndroid Build Coastguard Worker        num_classes = self.benchmark_definition['num_classes']
158*a65addddSAndroid Build Coastguard Worker        compiler_executable_name = self.benchmark_definition['compiler']
159*a65addddSAndroid Build Coastguard Worker
160*a65addddSAndroid Build Coastguard Worker        self.tmpdir = tempfile.gettempdir() + '/fruit-benchmark-dir'
161*a65addddSAndroid Build Coastguard Worker        ensure_empty_dir(self.tmpdir)
162*a65addddSAndroid Build Coastguard Worker        run_command(compiler_executable_name,
163*a65addddSAndroid Build Coastguard Worker                    args=compile_flags + [
164*a65addddSAndroid Build Coastguard Worker                        '-std=%s' % cxx_std,
165*a65addddSAndroid Build Coastguard Worker                        '-DMULTIPLIER=%s' % num_classes,
166*a65addddSAndroid Build Coastguard Worker                        self.fruit_benchmark_sources_dir + '/extras/benchmark/new_delete_benchmark.cpp',
167*a65addddSAndroid Build Coastguard Worker                        '-o',
168*a65addddSAndroid Build Coastguard Worker                        self.tmpdir + '/main',
169*a65addddSAndroid Build Coastguard Worker                    ])
170*a65addddSAndroid Build Coastguard Worker
171*a65addddSAndroid Build Coastguard Worker    def run(self):
172*a65addddSAndroid Build Coastguard Worker        loop_factor = self.benchmark_definition['loop_factor']
173*a65addddSAndroid Build Coastguard Worker        stdout, _ = run_command(self.tmpdir + '/main', args = [int(5000000 * loop_factor)])
174*a65addddSAndroid Build Coastguard Worker        return parse_results(stdout.splitlines())
175*a65addddSAndroid Build Coastguard Worker
176*a65addddSAndroid Build Coastguard Worker    def describe(self):
177*a65addddSAndroid Build Coastguard Worker        return self.benchmark_definition
178*a65addddSAndroid Build Coastguard Worker
179*a65addddSAndroid Build Coastguard Worker
180*a65addddSAndroid Build Coastguard Workerclass FruitSingleFileCompileTimeBenchmark(Benchmark):
181*a65addddSAndroid Build Coastguard Worker    def __init__(self, benchmark_definition: Dict[str, Any], fruit_sources_dir: str, fruit_build_dir: str, fruit_benchmark_sources_dir: str):
182*a65addddSAndroid Build Coastguard Worker        self.benchmark_definition = add_synthetic_benchmark_parameters(benchmark_definition, path_to_code_under_test=fruit_sources_dir)
183*a65addddSAndroid Build Coastguard Worker        self.fruit_sources_dir = fruit_sources_dir
184*a65addddSAndroid Build Coastguard Worker        self.fruit_build_dir = fruit_build_dir
185*a65addddSAndroid Build Coastguard Worker        self.fruit_benchmark_sources_dir = fruit_benchmark_sources_dir
186*a65addddSAndroid Build Coastguard Worker        num_bindings = self.benchmark_definition['num_bindings']
187*a65addddSAndroid Build Coastguard Worker        assert (num_bindings % 5) == 0, num_bindings
188*a65addddSAndroid Build Coastguard Worker
189*a65addddSAndroid Build Coastguard Worker    def prepare(self):
190*a65addddSAndroid Build Coastguard Worker        pass
191*a65addddSAndroid Build Coastguard Worker
192*a65addddSAndroid Build Coastguard Worker    def run(self):
193*a65addddSAndroid Build Coastguard Worker        start = timer()
194*a65addddSAndroid Build Coastguard Worker        cxx_std = self.benchmark_definition['cxx_std']
195*a65addddSAndroid Build Coastguard Worker        num_bindings = self.benchmark_definition['num_bindings']
196*a65addddSAndroid Build Coastguard Worker        compiler_executable_name = self.benchmark_definition['compiler']
197*a65addddSAndroid Build Coastguard Worker
198*a65addddSAndroid Build Coastguard Worker        run_command(compiler_executable_name,
199*a65addddSAndroid Build Coastguard Worker                    args = compile_flags + [
200*a65addddSAndroid Build Coastguard Worker                        '-std=%s' % cxx_std,
201*a65addddSAndroid Build Coastguard Worker                        '-DMULTIPLIER=%s' % (num_bindings // 5),
202*a65addddSAndroid Build Coastguard Worker                        '-I', self.fruit_sources_dir + '/include',
203*a65addddSAndroid Build Coastguard Worker                        '-I', self.fruit_build_dir + '/include',
204*a65addddSAndroid Build Coastguard Worker                        '-ftemplate-depth=1000',
205*a65addddSAndroid Build Coastguard Worker                        '-c',
206*a65addddSAndroid Build Coastguard Worker                        self.fruit_benchmark_sources_dir + '/extras/benchmark/compile_time_benchmark.cpp',
207*a65addddSAndroid Build Coastguard Worker                        '-o',
208*a65addddSAndroid Build Coastguard Worker                        '/dev/null',
209*a65addddSAndroid Build Coastguard Worker                    ])
210*a65addddSAndroid Build Coastguard Worker        end = timer()
211*a65addddSAndroid Build Coastguard Worker        return {"compile_time": end - start}
212*a65addddSAndroid Build Coastguard Worker
213*a65addddSAndroid Build Coastguard Worker    def describe(self):
214*a65addddSAndroid Build Coastguard Worker        return self.benchmark_definition
215*a65addddSAndroid Build Coastguard Worker
216*a65addddSAndroid Build Coastguard Worker
217*a65addddSAndroid Build Coastguard Workerdef ensure_empty_dir(dirname: str):
218*a65addddSAndroid Build Coastguard Worker    # We start by creating the directory instead of just calling rmtree with ignore_errors=True because that would ignore
219*a65addddSAndroid Build Coastguard Worker    # all errors, so we might otherwise go ahead even if the directory wasn't properly deleted.
220*a65addddSAndroid Build Coastguard Worker    os.makedirs(dirname, exist_ok=True)
221*a65addddSAndroid Build Coastguard Worker    shutil.rmtree(dirname)
222*a65addddSAndroid Build Coastguard Worker    os.makedirs(dirname)
223*a65addddSAndroid Build Coastguard Worker
224*a65addddSAndroid Build Coastguard Worker
225*a65addddSAndroid Build Coastguard Workerclass GenericGeneratedSourcesBenchmark(Benchmark):
226*a65addddSAndroid Build Coastguard Worker    def __init__(self,
227*a65addddSAndroid Build Coastguard Worker                 di_library,
228*a65addddSAndroid Build Coastguard Worker                 benchmark_definition,
229*a65addddSAndroid Build Coastguard Worker                 path_to_code_under_test=None,
230*a65addddSAndroid Build Coastguard Worker                 **other_args):
231*a65addddSAndroid Build Coastguard Worker        self.di_library = di_library
232*a65addddSAndroid Build Coastguard Worker        self.benchmark_definition = add_synthetic_benchmark_parameters(benchmark_definition, path_to_code_under_test=path_to_code_under_test)
233*a65addddSAndroid Build Coastguard Worker        self.other_args = other_args
234*a65addddSAndroid Build Coastguard Worker        self.arbitrary_file = None
235*a65addddSAndroid Build Coastguard Worker
236*a65addddSAndroid Build Coastguard Worker    def prepare_compile_benchmark(self):
237*a65addddSAndroid Build Coastguard Worker        num_classes = self.benchmark_definition['num_classes']
238*a65addddSAndroid Build Coastguard Worker        cxx_std = self.benchmark_definition['cxx_std']
239*a65addddSAndroid Build Coastguard Worker        compiler_executable_name = self.benchmark_definition['compiler']
240*a65addddSAndroid Build Coastguard Worker        benchmark_generation_flags = {flag_name: True for flag_name in self.benchmark_definition['benchmark_generation_flags']}
241*a65addddSAndroid Build Coastguard Worker
242*a65addddSAndroid Build Coastguard Worker        self.tmpdir = tempfile.gettempdir() + '/fruit-benchmark-dir'
243*a65addddSAndroid Build Coastguard Worker        ensure_empty_dir(self.tmpdir)
244*a65addddSAndroid Build Coastguard Worker        num_classes_with_no_deps = int(num_classes * 0.1)
245*a65addddSAndroid Build Coastguard Worker        return generate_benchmark(
246*a65addddSAndroid Build Coastguard Worker            compiler=compiler_executable_name,
247*a65addddSAndroid Build Coastguard Worker            num_components_with_no_deps=num_classes_with_no_deps,
248*a65addddSAndroid Build Coastguard Worker            num_components_with_deps=num_classes - num_classes_with_no_deps,
249*a65addddSAndroid Build Coastguard Worker            num_deps=10,
250*a65addddSAndroid Build Coastguard Worker            output_dir=self.tmpdir,
251*a65addddSAndroid Build Coastguard Worker            cxx_std=cxx_std,
252*a65addddSAndroid Build Coastguard Worker            di_library=self.di_library,
253*a65addddSAndroid Build Coastguard Worker            **benchmark_generation_flags,
254*a65addddSAndroid Build Coastguard Worker            **self.other_args)
255*a65addddSAndroid Build Coastguard Worker
256*a65addddSAndroid Build Coastguard Worker    def run_make_build(self):
257*a65addddSAndroid Build Coastguard Worker        run_command('make', args=make_args, cwd=self.tmpdir)
258*a65addddSAndroid Build Coastguard Worker
259*a65addddSAndroid Build Coastguard Worker    def prepare_incremental_compile_benchmark(self):
260*a65addddSAndroid Build Coastguard Worker        files = self.prepare_compile_benchmark()
261*a65addddSAndroid Build Coastguard Worker        self.run_make_build()
262*a65addddSAndroid Build Coastguard Worker        files = list(sorted(file for file in files if file.endswith('.h')))
263*a65addddSAndroid Build Coastguard Worker        # 5 files, equally spaced (but not at beginning/end) in the sorted sequence.
264*a65addddSAndroid Build Coastguard Worker        num_files_changed = 5
265*a65addddSAndroid Build Coastguard Worker        self.arbitrary_files = [files[i * (len(files) // (num_files_changed + 2))]
266*a65addddSAndroid Build Coastguard Worker                                for i in range(1, num_files_changed + 1)]
267*a65addddSAndroid Build Coastguard Worker
268*a65addddSAndroid Build Coastguard Worker    def prepare_compile_memory_benchmark(self):
269*a65addddSAndroid Build Coastguard Worker        self.prepare_compile_benchmark()
270*a65addddSAndroid Build Coastguard Worker        self.run_compile_memory_benchmark()
271*a65addddSAndroid Build Coastguard Worker
272*a65addddSAndroid Build Coastguard Worker    def prepare_runtime_benchmark(self):
273*a65addddSAndroid Build Coastguard Worker        self.prepare_compile_benchmark()
274*a65addddSAndroid Build Coastguard Worker        self.run_make_build()
275*a65addddSAndroid Build Coastguard Worker
276*a65addddSAndroid Build Coastguard Worker    def prepare_startup_benchmark(self):
277*a65addddSAndroid Build Coastguard Worker        self.prepare_compile_benchmark()
278*a65addddSAndroid Build Coastguard Worker        self.run_make_build()
279*a65addddSAndroid Build Coastguard Worker        run_command('strip', args=[self.tmpdir + '/main'])
280*a65addddSAndroid Build Coastguard Worker
281*a65addddSAndroid Build Coastguard Worker    def prepare_executable_size_benchmark(self):
282*a65addddSAndroid Build Coastguard Worker        self.prepare_runtime_benchmark()
283*a65addddSAndroid Build Coastguard Worker        run_command('strip', args=[self.tmpdir + '/main'])
284*a65addddSAndroid Build Coastguard Worker
285*a65addddSAndroid Build Coastguard Worker    def run_compile_benchmark(self):
286*a65addddSAndroid Build Coastguard Worker        run_command('make',
287*a65addddSAndroid Build Coastguard Worker                    args=make_args + ['clean'],
288*a65addddSAndroid Build Coastguard Worker                    cwd=self.tmpdir)
289*a65addddSAndroid Build Coastguard Worker        start = timer()
290*a65addddSAndroid Build Coastguard Worker        self.run_make_build()
291*a65addddSAndroid Build Coastguard Worker        end = timer()
292*a65addddSAndroid Build Coastguard Worker        result = {'compile_time': end - start}
293*a65addddSAndroid Build Coastguard Worker        return result
294*a65addddSAndroid Build Coastguard Worker
295*a65addddSAndroid Build Coastguard Worker    def run_incremental_compile_benchmark(self):
296*a65addddSAndroid Build Coastguard Worker        run_command('touch', args=self.arbitrary_files, cwd=self.tmpdir)
297*a65addddSAndroid Build Coastguard Worker        start = timer()
298*a65addddSAndroid Build Coastguard Worker        self.run_make_build()
299*a65addddSAndroid Build Coastguard Worker        end = timer()
300*a65addddSAndroid Build Coastguard Worker        result = {'incremental_compile_time': end - start}
301*a65addddSAndroid Build Coastguard Worker        return result
302*a65addddSAndroid Build Coastguard Worker
303*a65addddSAndroid Build Coastguard Worker    def run_compile_memory_benchmark(self):
304*a65addddSAndroid Build Coastguard Worker        run_command('make', args=make_args + ['clean'], cwd=self.tmpdir)
305*a65addddSAndroid Build Coastguard Worker        run_command('make', args=make_args + ['main_ram.txt'], cwd=self.tmpdir)
306*a65addddSAndroid Build Coastguard Worker        with open(self.tmpdir + '/main_ram.txt') as f:
307*a65addddSAndroid Build Coastguard Worker            ram_usages = [int(n)*1024 for n in f.readlines()]
308*a65addddSAndroid Build Coastguard Worker        return {
309*a65addddSAndroid Build Coastguard Worker            'total_max_ram_usage': sum(ram_usages),
310*a65addddSAndroid Build Coastguard Worker            'max_ram_usage': max(ram_usages),
311*a65addddSAndroid Build Coastguard Worker        }
312*a65addddSAndroid Build Coastguard Worker
313*a65addddSAndroid Build Coastguard Worker    def run_runtime_benchmark(self):
314*a65addddSAndroid Build Coastguard Worker        num_classes = self.benchmark_definition['num_classes']
315*a65addddSAndroid Build Coastguard Worker        loop_factor = self.benchmark_definition['loop_factor']
316*a65addddSAndroid Build Coastguard Worker
317*a65addddSAndroid Build Coastguard Worker        results, _ = run_command(self.tmpdir + '/main',
318*a65addddSAndroid Build Coastguard Worker                                 args = [
319*a65addddSAndroid Build Coastguard Worker                                     # 40M loops with 100 classes, 40M with 1000
320*a65addddSAndroid Build Coastguard Worker                                     int(4 * 1000 * 1000 * 1000 * loop_factor / num_classes),
321*a65addddSAndroid Build Coastguard Worker                                 ])
322*a65addddSAndroid Build Coastguard Worker        return parse_results(results.splitlines())
323*a65addddSAndroid Build Coastguard Worker
324*a65addddSAndroid Build Coastguard Worker    def run_startup_benchmark(self):
325*a65addddSAndroid Build Coastguard Worker        n = 1000
326*a65addddSAndroid Build Coastguard Worker        start = timer()
327*a65addddSAndroid Build Coastguard Worker        for i in range(0, n):
328*a65addddSAndroid Build Coastguard Worker            run_command(self.tmpdir + '/main', args = [])
329*a65addddSAndroid Build Coastguard Worker        end = timer()
330*a65addddSAndroid Build Coastguard Worker        result = {'startup_time': (end - start) / n}
331*a65addddSAndroid Build Coastguard Worker        return result
332*a65addddSAndroid Build Coastguard Worker
333*a65addddSAndroid Build Coastguard Worker    def run_executable_size_benchmark(self):
334*a65addddSAndroid Build Coastguard Worker        wc_result, _ = run_command('wc', args=['-c', self.tmpdir + '/main'])
335*a65addddSAndroid Build Coastguard Worker        num_bytes = wc_result.splitlines()[0].split(' ')[0]
336*a65addddSAndroid Build Coastguard Worker        return {'num_bytes': float(num_bytes)}
337*a65addddSAndroid Build Coastguard Worker
338*a65addddSAndroid Build Coastguard Worker    def describe(self):
339*a65addddSAndroid Build Coastguard Worker        return self.benchmark_definition
340*a65addddSAndroid Build Coastguard Worker
341*a65addddSAndroid Build Coastguard Worker
342*a65addddSAndroid Build Coastguard Workerclass CompileTimeBenchmark(GenericGeneratedSourcesBenchmark):
343*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
344*a65addddSAndroid Build Coastguard Worker        super().__init__(generate_runtime_bench_code=False,
345*a65addddSAndroid Build Coastguard Worker                         **kwargs)
346*a65addddSAndroid Build Coastguard Worker
347*a65addddSAndroid Build Coastguard Worker    def prepare(self):
348*a65addddSAndroid Build Coastguard Worker        self.prepare_compile_benchmark()
349*a65addddSAndroid Build Coastguard Worker
350*a65addddSAndroid Build Coastguard Worker    def run(self):
351*a65addddSAndroid Build Coastguard Worker        return self.run_compile_benchmark()
352*a65addddSAndroid Build Coastguard Worker
353*a65addddSAndroid Build Coastguard Workerclass IncrementalCompileTimeBenchmark(GenericGeneratedSourcesBenchmark):
354*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
355*a65addddSAndroid Build Coastguard Worker        super().__init__(generate_runtime_bench_code=False,
356*a65addddSAndroid Build Coastguard Worker                         **kwargs)
357*a65addddSAndroid Build Coastguard Worker
358*a65addddSAndroid Build Coastguard Worker    def prepare(self):
359*a65addddSAndroid Build Coastguard Worker        self.prepare_incremental_compile_benchmark()
360*a65addddSAndroid Build Coastguard Worker
361*a65addddSAndroid Build Coastguard Worker    def run(self):
362*a65addddSAndroid Build Coastguard Worker        return self.run_incremental_compile_benchmark()
363*a65addddSAndroid Build Coastguard Worker
364*a65addddSAndroid Build Coastguard Workerclass CompileMemoryBenchmark(GenericGeneratedSourcesBenchmark):
365*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
366*a65addddSAndroid Build Coastguard Worker        super().__init__(generate_runtime_bench_code=False,
367*a65addddSAndroid Build Coastguard Worker                         **kwargs)
368*a65addddSAndroid Build Coastguard Worker
369*a65addddSAndroid Build Coastguard Worker    def prepare(self):
370*a65addddSAndroid Build Coastguard Worker        self.prepare_compile_memory_benchmark()
371*a65addddSAndroid Build Coastguard Worker
372*a65addddSAndroid Build Coastguard Worker    def run(self):
373*a65addddSAndroid Build Coastguard Worker        return self.run_compile_memory_benchmark()
374*a65addddSAndroid Build Coastguard Worker
375*a65addddSAndroid Build Coastguard Workerclass StartupTimeBenchmark(GenericGeneratedSourcesBenchmark):
376*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
377*a65addddSAndroid Build Coastguard Worker        super().__init__(generate_runtime_bench_code=False,
378*a65addddSAndroid Build Coastguard Worker                         **kwargs)
379*a65addddSAndroid Build Coastguard Worker
380*a65addddSAndroid Build Coastguard Worker    def prepare(self):
381*a65addddSAndroid Build Coastguard Worker        self.prepare_startup_benchmark()
382*a65addddSAndroid Build Coastguard Worker
383*a65addddSAndroid Build Coastguard Worker    def run(self):
384*a65addddSAndroid Build Coastguard Worker        return self.run_startup_benchmark()
385*a65addddSAndroid Build Coastguard Worker
386*a65addddSAndroid Build Coastguard Workerclass RunTimeBenchmark(GenericGeneratedSourcesBenchmark):
387*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
388*a65addddSAndroid Build Coastguard Worker        super().__init__(generate_runtime_bench_code=True,
389*a65addddSAndroid Build Coastguard Worker                         **kwargs)
390*a65addddSAndroid Build Coastguard Worker
391*a65addddSAndroid Build Coastguard Worker    def prepare(self):
392*a65addddSAndroid Build Coastguard Worker        self.prepare_runtime_benchmark()
393*a65addddSAndroid Build Coastguard Worker
394*a65addddSAndroid Build Coastguard Worker    def run(self):
395*a65addddSAndroid Build Coastguard Worker        return self.run_runtime_benchmark()
396*a65addddSAndroid Build Coastguard Worker
397*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
398*a65addddSAndroid Build Coastguard Workerclass ExecutableSizeBenchmark(GenericGeneratedSourcesBenchmark):
399*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
400*a65addddSAndroid Build Coastguard Worker        super().__init__(generate_runtime_bench_code=False,
401*a65addddSAndroid Build Coastguard Worker                         **kwargs)
402*a65addddSAndroid Build Coastguard Worker
403*a65addddSAndroid Build Coastguard Worker    def prepare(self):
404*a65addddSAndroid Build Coastguard Worker        self.prepare_executable_size_benchmark()
405*a65addddSAndroid Build Coastguard Worker
406*a65addddSAndroid Build Coastguard Worker    def run(self):
407*a65addddSAndroid Build Coastguard Worker        return self.run_executable_size_benchmark()
408*a65addddSAndroid Build Coastguard Worker
409*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
410*a65addddSAndroid Build Coastguard Workerclass ExecutableSizeBenchmarkWithoutExceptionsAndRtti(ExecutableSizeBenchmark):
411*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
412*a65addddSAndroid Build Coastguard Worker        super().__init__(use_exceptions=False,
413*a65addddSAndroid Build Coastguard Worker                         use_rtti=False,
414*a65addddSAndroid Build Coastguard Worker                         **kwargs)
415*a65addddSAndroid Build Coastguard Worker
416*a65addddSAndroid Build Coastguard Workerclass FruitCompileTimeBenchmark(CompileTimeBenchmark):
417*a65addddSAndroid Build Coastguard Worker    def __init__(self, fruit_sources_dir, **kwargs):
418*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='fruit',
419*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=fruit_sources_dir,
420*a65addddSAndroid Build Coastguard Worker                         fruit_sources_dir=fruit_sources_dir,
421*a65addddSAndroid Build Coastguard Worker                         **kwargs)
422*a65addddSAndroid Build Coastguard Worker
423*a65addddSAndroid Build Coastguard Workerclass FruitIncrementalCompileTimeBenchmark(IncrementalCompileTimeBenchmark):
424*a65addddSAndroid Build Coastguard Worker    def __init__(self, fruit_sources_dir, **kwargs):
425*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='fruit',
426*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=fruit_sources_dir,
427*a65addddSAndroid Build Coastguard Worker                         fruit_sources_dir=fruit_sources_dir,
428*a65addddSAndroid Build Coastguard Worker                         **kwargs)
429*a65addddSAndroid Build Coastguard Worker
430*a65addddSAndroid Build Coastguard Workerclass FruitCompileMemoryBenchmark(CompileMemoryBenchmark):
431*a65addddSAndroid Build Coastguard Worker    def __init__(self, fruit_sources_dir, **kwargs):
432*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='fruit',
433*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=fruit_sources_dir,
434*a65addddSAndroid Build Coastguard Worker                         fruit_sources_dir=fruit_sources_dir,
435*a65addddSAndroid Build Coastguard Worker                         **kwargs)
436*a65addddSAndroid Build Coastguard Worker
437*a65addddSAndroid Build Coastguard Workerclass FruitRunTimeBenchmark(RunTimeBenchmark):
438*a65addddSAndroid Build Coastguard Worker    def __init__(self, fruit_sources_dir, **kwargs):
439*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='fruit',
440*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=fruit_sources_dir,
441*a65addddSAndroid Build Coastguard Worker                         fruit_sources_dir=fruit_sources_dir,
442*a65addddSAndroid Build Coastguard Worker                         **kwargs)
443*a65addddSAndroid Build Coastguard Worker
444*a65addddSAndroid Build Coastguard Workerclass FruitStartupTimeBenchmark(StartupTimeBenchmark):
445*a65addddSAndroid Build Coastguard Worker    def __init__(self, fruit_sources_dir, **kwargs):
446*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='fruit',
447*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=fruit_sources_dir,
448*a65addddSAndroid Build Coastguard Worker                         fruit_sources_dir=fruit_sources_dir,
449*a65addddSAndroid Build Coastguard Worker                         **kwargs)
450*a65addddSAndroid Build Coastguard Worker
451*a65addddSAndroid Build Coastguard Workerclass FruitStartupTimeWithNormalizedComponentBenchmark(FruitStartupTimeBenchmark):
452*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
453*a65addddSAndroid Build Coastguard Worker        super().__init__(use_normalized_component=True,
454*a65addddSAndroid Build Coastguard Worker                         **kwargs)
455*a65addddSAndroid Build Coastguard Worker
456*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
457*a65addddSAndroid Build Coastguard Workerclass FruitExecutableSizeBenchmark(ExecutableSizeBenchmark):
458*a65addddSAndroid Build Coastguard Worker    def __init__(self, fruit_sources_dir, **kwargs):
459*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='fruit',
460*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=fruit_sources_dir,
461*a65addddSAndroid Build Coastguard Worker                         fruit_sources_dir=fruit_sources_dir,
462*a65addddSAndroid Build Coastguard Worker                         **kwargs)
463*a65addddSAndroid Build Coastguard Worker
464*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
465*a65addddSAndroid Build Coastguard Workerclass FruitExecutableSizeBenchmarkWithoutExceptionsAndRtti(ExecutableSizeBenchmarkWithoutExceptionsAndRtti):
466*a65addddSAndroid Build Coastguard Worker    def __init__(self, fruit_sources_dir, **kwargs):
467*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='fruit',
468*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=fruit_sources_dir,
469*a65addddSAndroid Build Coastguard Worker                         fruit_sources_dir=fruit_sources_dir,
470*a65addddSAndroid Build Coastguard Worker                         **kwargs)
471*a65addddSAndroid Build Coastguard Worker
472*a65addddSAndroid Build Coastguard Workerclass BoostDiCompileTimeBenchmark(CompileTimeBenchmark):
473*a65addddSAndroid Build Coastguard Worker    def __init__(self, boost_di_sources_dir, **kwargs):
474*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='boost_di',
475*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=boost_di_sources_dir,
476*a65addddSAndroid Build Coastguard Worker                         boost_di_sources_dir=boost_di_sources_dir,
477*a65addddSAndroid Build Coastguard Worker                         **kwargs)
478*a65addddSAndroid Build Coastguard Worker
479*a65addddSAndroid Build Coastguard Workerclass BoostDiIncrementalCompileTimeBenchmark(IncrementalCompileTimeBenchmark):
480*a65addddSAndroid Build Coastguard Worker    def __init__(self, boost_di_sources_dir, **kwargs):
481*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='boost_di',
482*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=boost_di_sources_dir,
483*a65addddSAndroid Build Coastguard Worker                         boost_di_sources_dir=boost_di_sources_dir,
484*a65addddSAndroid Build Coastguard Worker                         **kwargs)
485*a65addddSAndroid Build Coastguard Worker
486*a65addddSAndroid Build Coastguard Workerclass BoostDiCompileMemoryBenchmark(CompileMemoryBenchmark):
487*a65addddSAndroid Build Coastguard Worker    def __init__(self, boost_di_sources_dir, **kwargs):
488*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='boost_di',
489*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=boost_di_sources_dir,
490*a65addddSAndroid Build Coastguard Worker                         boost_di_sources_dir=boost_di_sources_dir,
491*a65addddSAndroid Build Coastguard Worker                         **kwargs)
492*a65addddSAndroid Build Coastguard Worker
493*a65addddSAndroid Build Coastguard Workerclass BoostDiRunTimeBenchmark(RunTimeBenchmark):
494*a65addddSAndroid Build Coastguard Worker    def __init__(self, boost_di_sources_dir, **kwargs):
495*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='boost_di',
496*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=boost_di_sources_dir,
497*a65addddSAndroid Build Coastguard Worker                         boost_di_sources_dir=boost_di_sources_dir,
498*a65addddSAndroid Build Coastguard Worker                         **kwargs)
499*a65addddSAndroid Build Coastguard Worker
500*a65addddSAndroid Build Coastguard Workerclass BoostDiStartupTimeBenchmark(StartupTimeBenchmark):
501*a65addddSAndroid Build Coastguard Worker    def __init__(self, boost_di_sources_dir, **kwargs):
502*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='boost_di',
503*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=boost_di_sources_dir,
504*a65addddSAndroid Build Coastguard Worker                         boost_di_sources_dir=boost_di_sources_dir,
505*a65addddSAndroid Build Coastguard Worker                         **kwargs)
506*a65addddSAndroid Build Coastguard Worker
507*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
508*a65addddSAndroid Build Coastguard Workerclass BoostDiExecutableSizeBenchmark(ExecutableSizeBenchmark):
509*a65addddSAndroid Build Coastguard Worker    def __init__(self, boost_di_sources_dir, **kwargs):
510*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='boost_di',
511*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=boost_di_sources_dir,
512*a65addddSAndroid Build Coastguard Worker                         boost_di_sources_dir=boost_di_sources_dir,
513*a65addddSAndroid Build Coastguard Worker                         **kwargs)
514*a65addddSAndroid Build Coastguard Worker
515*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
516*a65addddSAndroid Build Coastguard Workerclass BoostDiExecutableSizeBenchmarkWithoutExceptionsAndRtti(ExecutableSizeBenchmarkWithoutExceptionsAndRtti):
517*a65addddSAndroid Build Coastguard Worker    def __init__(self, boost_di_sources_dir, **kwargs):
518*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='boost_di',
519*a65addddSAndroid Build Coastguard Worker                         path_to_code_under_test=boost_di_sources_dir,
520*a65addddSAndroid Build Coastguard Worker                         boost_di_sources_dir=boost_di_sources_dir,
521*a65addddSAndroid Build Coastguard Worker                         **kwargs)
522*a65addddSAndroid Build Coastguard Worker
523*a65addddSAndroid Build Coastguard Workerclass SimpleDiCompileTimeBenchmark(CompileTimeBenchmark):
524*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
525*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='none',
526*a65addddSAndroid Build Coastguard Worker                         **kwargs)
527*a65addddSAndroid Build Coastguard Worker
528*a65addddSAndroid Build Coastguard Workerclass SimpleDiIncrementalCompileTimeBenchmark(IncrementalCompileTimeBenchmark):
529*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
530*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='none',
531*a65addddSAndroid Build Coastguard Worker                         **kwargs)
532*a65addddSAndroid Build Coastguard Worker
533*a65addddSAndroid Build Coastguard Workerclass SimpleDiCompileMemoryBenchmark(CompileMemoryBenchmark):
534*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
535*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='none',
536*a65addddSAndroid Build Coastguard Worker                         **kwargs)
537*a65addddSAndroid Build Coastguard Worker
538*a65addddSAndroid Build Coastguard Workerclass SimpleDiRunTimeBenchmark(RunTimeBenchmark):
539*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
540*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='none',
541*a65addddSAndroid Build Coastguard Worker                         **kwargs)
542*a65addddSAndroid Build Coastguard Worker
543*a65addddSAndroid Build Coastguard Workerclass SimpleDiStartupTimeBenchmark(StartupTimeBenchmark):
544*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
545*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='none',
546*a65addddSAndroid Build Coastguard Worker                         **kwargs)
547*a65addddSAndroid Build Coastguard Worker
548*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
549*a65addddSAndroid Build Coastguard Workerclass SimpleDiExecutableSizeBenchmark(ExecutableSizeBenchmark):
550*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
551*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='none',
552*a65addddSAndroid Build Coastguard Worker                         **kwargs)
553*a65addddSAndroid Build Coastguard Worker
554*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
555*a65addddSAndroid Build Coastguard Workerclass SimpleDiExecutableSizeBenchmarkWithoutExceptionsAndRtti(ExecutableSizeBenchmarkWithoutExceptionsAndRtti):
556*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
557*a65addddSAndroid Build Coastguard Worker        super().__init__(di_library='none',
558*a65addddSAndroid Build Coastguard Worker                         **kwargs)
559*a65addddSAndroid Build Coastguard Worker
560*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesCompileTimeBenchmark(SimpleDiCompileTimeBenchmark):
561*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
562*a65addddSAndroid Build Coastguard Worker        super().__init__(use_interfaces=True, **kwargs)
563*a65addddSAndroid Build Coastguard Worker
564*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesIncrementalCompileTimeBenchmark(SimpleDiIncrementalCompileTimeBenchmark):
565*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
566*a65addddSAndroid Build Coastguard Worker        super().__init__(use_interfaces=True, **kwargs)
567*a65addddSAndroid Build Coastguard Worker
568*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesCompileMemoryBenchmark(SimpleDiCompileMemoryBenchmark):
569*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
570*a65addddSAndroid Build Coastguard Worker        super().__init__(use_interfaces=True, **kwargs)
571*a65addddSAndroid Build Coastguard Worker
572*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesRunTimeBenchmark(SimpleDiRunTimeBenchmark):
573*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
574*a65addddSAndroid Build Coastguard Worker        super().__init__(use_interfaces=True, **kwargs)
575*a65addddSAndroid Build Coastguard Worker
576*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesStartupTimeBenchmark(SimpleDiStartupTimeBenchmark):
577*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
578*a65addddSAndroid Build Coastguard Worker        super().__init__(use_interfaces=True, **kwargs)
579*a65addddSAndroid Build Coastguard Worker
580*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
581*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesExecutableSizeBenchmark(SimpleDiExecutableSizeBenchmark):
582*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
583*a65addddSAndroid Build Coastguard Worker        super().__init__(use_interfaces=True, **kwargs)
584*a65addddSAndroid Build Coastguard Worker
585*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
586*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesExecutableSizeBenchmarkWithoutExceptionsAndRtti(SimpleDiExecutableSizeBenchmarkWithoutExceptionsAndRtti):
587*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
588*a65addddSAndroid Build Coastguard Worker        super().__init__(use_interfaces=True, **kwargs)
589*a65addddSAndroid Build Coastguard Worker
590*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesAndNewDeleteCompileTimeBenchmark(SimpleDiWithInterfacesCompileTimeBenchmark):
591*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
592*a65addddSAndroid Build Coastguard Worker        super().__init__(use_new_delete=True, **kwargs)
593*a65addddSAndroid Build Coastguard Worker
594*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesAndNewDeleteIncrementalCompileTimeBenchmark(SimpleDiWithInterfacesIncrementalCompileTimeBenchmark):
595*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
596*a65addddSAndroid Build Coastguard Worker        super().__init__(use_new_delete=True, **kwargs)
597*a65addddSAndroid Build Coastguard Worker
598*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesAndNewDeleteCompileMemoryBenchmark(SimpleDiWithInterfacesCompileMemoryBenchmark):
599*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
600*a65addddSAndroid Build Coastguard Worker        super().__init__(use_new_delete=True, **kwargs)
601*a65addddSAndroid Build Coastguard Worker
602*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesAndNewDeleteRunTimeBenchmark(SimpleDiWithInterfacesRunTimeBenchmark):
603*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
604*a65addddSAndroid Build Coastguard Worker        super().__init__(use_new_delete=True, **kwargs)
605*a65addddSAndroid Build Coastguard Worker
606*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesAndNewDeleteStartupTimeBenchmark(SimpleDiWithInterfacesStartupTimeBenchmark):
607*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
608*a65addddSAndroid Build Coastguard Worker        super().__init__(use_new_delete=True, **kwargs)
609*a65addddSAndroid Build Coastguard Worker
610*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
611*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesAndNewDeleteExecutableSizeBenchmark(SimpleDiWithInterfacesExecutableSizeBenchmark):
612*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
613*a65addddSAndroid Build Coastguard Worker        super().__init__(use_new_delete=True, **kwargs)
614*a65addddSAndroid Build Coastguard Worker
615*a65addddSAndroid Build Coastguard Worker# This is not really a 'benchmark', but we consider it as such to reuse the benchmark infrastructure.
616*a65addddSAndroid Build Coastguard Workerclass SimpleDiWithInterfacesAndNewDeleteExecutableSizeBenchmarkWithoutExceptionsAndRtti(SimpleDiWithInterfacesExecutableSizeBenchmarkWithoutExceptionsAndRtti):
617*a65addddSAndroid Build Coastguard Worker    def __init__(self, **kwargs):
618*a65addddSAndroid Build Coastguard Worker        super().__init__(use_new_delete=True, **kwargs)
619*a65addddSAndroid Build Coastguard Worker
620*a65addddSAndroid Build Coastguard Worker
621*a65addddSAndroid Build Coastguard Workerdef round_to_significant_digits(n: float, num_significant_digits: int) -> float:
622*a65addddSAndroid Build Coastguard Worker    if n <= 0:
623*a65addddSAndroid Build Coastguard Worker        # We special-case this, otherwise the log10 below will fail.
624*a65addddSAndroid Build Coastguard Worker        return 0
625*a65addddSAndroid Build Coastguard Worker    return round(n, num_significant_digits - int(floor(log10(n))) - 1)
626*a65addddSAndroid Build Coastguard Worker
627*a65addddSAndroid Build Coastguard Workerdef run_benchmark(benchmark: Benchmark, max_runs: int, timeout_hours: int, output_file: str, min_runs: int=3) -> None:
628*a65addddSAndroid Build Coastguard Worker    def run_benchmark_once():
629*a65addddSAndroid Build Coastguard Worker        print('Running benchmark... ', end='', flush=True)
630*a65addddSAndroid Build Coastguard Worker        result = benchmark.run()
631*a65addddSAndroid Build Coastguard Worker        print(result)
632*a65addddSAndroid Build Coastguard Worker        for dimension, value in result.items():
633*a65addddSAndroid Build Coastguard Worker            results_by_dimension[dimension] += [value]
634*a65addddSAndroid Build Coastguard Worker
635*a65addddSAndroid Build Coastguard Worker    results_by_dimension = defaultdict(lambda: [])
636*a65addddSAndroid Build Coastguard Worker    print('Preparing for benchmark... ', end='', flush=True)
637*a65addddSAndroid Build Coastguard Worker    benchmark.prepare()
638*a65addddSAndroid Build Coastguard Worker    print('Done.')
639*a65addddSAndroid Build Coastguard Worker
640*a65addddSAndroid Build Coastguard Worker    start_time = timer()
641*a65addddSAndroid Build Coastguard Worker
642*a65addddSAndroid Build Coastguard Worker    # Run at least min_runs times
643*a65addddSAndroid Build Coastguard Worker    for i in range(min_runs):
644*a65addddSAndroid Build Coastguard Worker        run_benchmark_once()
645*a65addddSAndroid Build Coastguard Worker
646*a65addddSAndroid Build Coastguard Worker    # Then consider running a few more times to get the desired precision.
647*a65addddSAndroid Build Coastguard Worker    while True:
648*a65addddSAndroid Build Coastguard Worker        if timer() - start_time > timeout_hours * 3600:
649*a65addddSAndroid Build Coastguard Worker            print("Warning: timed out, couldn't determine a result with the desired precision.")
650*a65addddSAndroid Build Coastguard Worker            break
651*a65addddSAndroid Build Coastguard Worker
652*a65addddSAndroid Build Coastguard Worker        for dimension, results in results_by_dimension.items():
653*a65addddSAndroid Build Coastguard Worker            if all(result == results[0] for result in results):
654*a65addddSAndroid Build Coastguard Worker                # If all results are exactly the same the code below misbehaves. We don't need to run again in this case.
655*a65addddSAndroid Build Coastguard Worker                continue
656*a65addddSAndroid Build Coastguard Worker            confidence_interval = stats.DescrStatsW(results).tconfint_mean(0.05)
657*a65addddSAndroid Build Coastguard Worker            confidence_interval_2dig = (round_to_significant_digits(confidence_interval[0], 2),
658*a65addddSAndroid Build Coastguard Worker                                        round_to_significant_digits(confidence_interval[1], 2))
659*a65addddSAndroid Build Coastguard Worker            if abs(confidence_interval_2dig[0] - confidence_interval_2dig[1]) > numpy.finfo(float).eps * 10:
660*a65addddSAndroid Build Coastguard Worker                if len(results) < max_runs:
661*a65addddSAndroid Build Coastguard Worker                    print("Running again to get more precision on the metric %s. Current confidence interval: [%.3g, %.3g]" % (
662*a65addddSAndroid Build Coastguard Worker                        dimension, confidence_interval[0], confidence_interval[1]))
663*a65addddSAndroid Build Coastguard Worker                    break
664*a65addddSAndroid Build Coastguard Worker                else:
665*a65addddSAndroid Build Coastguard Worker                    print("Warning: couldn't determine a precise result for the metric %s. Confidence interval: [%.3g, %.3g]" % (
666*a65addddSAndroid Build Coastguard Worker                        dimension, confidence_interval[0], confidence_interval[1]))
667*a65addddSAndroid Build Coastguard Worker        else:
668*a65addddSAndroid Build Coastguard Worker            # We've reached sufficient precision in all metrics, or we've reached the max number of runs.
669*a65addddSAndroid Build Coastguard Worker            break
670*a65addddSAndroid Build Coastguard Worker
671*a65addddSAndroid Build Coastguard Worker        run_benchmark_once()
672*a65addddSAndroid Build Coastguard Worker
673*a65addddSAndroid Build Coastguard Worker    # We've reached the desired precision in all dimensions or reached the maximum number of runs. Record the results.
674*a65addddSAndroid Build Coastguard Worker    rounded_confidence_intervals_by_dimension = {}
675*a65addddSAndroid Build Coastguard Worker    confidence_intervals_by_dimension = {}
676*a65addddSAndroid Build Coastguard Worker    for dimension, results in results_by_dimension.items():
677*a65addddSAndroid Build Coastguard Worker        confidence_interval = stats.DescrStatsW(results).tconfint_mean(0.05)
678*a65addddSAndroid Build Coastguard Worker        confidence_interval_2dig = (round_to_significant_digits(confidence_interval[0], 2),
679*a65addddSAndroid Build Coastguard Worker                                    round_to_significant_digits(confidence_interval[1], 2))
680*a65addddSAndroid Build Coastguard Worker        rounded_confidence_intervals_by_dimension[dimension] = confidence_interval_2dig
681*a65addddSAndroid Build Coastguard Worker        confidence_intervals_by_dimension[dimension] = (confidence_interval, confidence_interval_2dig)
682*a65addddSAndroid Build Coastguard Worker    with open(output_file, 'a') as f:
683*a65addddSAndroid Build Coastguard Worker        json.dump({"benchmark": benchmark.describe(), "results": confidence_intervals_by_dimension}, f)
684*a65addddSAndroid Build Coastguard Worker        print(file=f)
685*a65addddSAndroid Build Coastguard Worker    print('Benchmark finished. Result: ', rounded_confidence_intervals_by_dimension)
686*a65addddSAndroid Build Coastguard Worker    print()
687*a65addddSAndroid Build Coastguard Worker
688*a65addddSAndroid Build Coastguard Worker
689*a65addddSAndroid Build Coastguard Workerdef expand_benchmark_definition(benchmark_definition: Dict[str, Any]) -> List[Dict[str, Tuple[Any]]]:
690*a65addddSAndroid Build Coastguard Worker    """
691*a65addddSAndroid Build Coastguard Worker    Takes a benchmark definition, e.g.:
692*a65addddSAndroid Build Coastguard Worker    [{name: 'foo', compiler: ['g++-5', 'g++-6']},
693*a65addddSAndroid Build Coastguard Worker     {name: ['bar', 'baz'], compiler: ['g++-5'], cxx_std: 'c++14'}]
694*a65addddSAndroid Build Coastguard Worker
695*a65addddSAndroid Build Coastguard Worker    And expands it into the individual benchmarks to run, in the example above:
696*a65addddSAndroid Build Coastguard Worker    [{name: 'foo', compiler: 'g++-5'},
697*a65addddSAndroid Build Coastguard Worker     {name: 'foo', compiler: 'g++-6'},
698*a65addddSAndroid Build Coastguard Worker     {name: 'bar', compiler: 'g++-5', cxx_std: 'c++14'},
699*a65addddSAndroid Build Coastguard Worker     {name: 'baz', compiler: 'g++-5', cxx_std: 'c++14'}]
700*a65addddSAndroid Build Coastguard Worker    """
701*a65addddSAndroid Build Coastguard Worker    dict_keys = sorted(benchmark_definition.keys())
702*a65addddSAndroid Build Coastguard Worker    # Turn non-list values into single-item lists.
703*a65addddSAndroid Build Coastguard Worker    benchmark_definition = {dict_key: value if isinstance(value, list) else [value]
704*a65addddSAndroid Build Coastguard Worker                            for dict_key, value in benchmark_definition.items()}
705*a65addddSAndroid Build Coastguard Worker    # Compute the cartesian product of the value lists
706*a65addddSAndroid Build Coastguard Worker    value_combinations = itertools.product(*(benchmark_definition[dict_key] for dict_key in dict_keys))
707*a65addddSAndroid Build Coastguard Worker    # Then turn the result back into a dict.
708*a65addddSAndroid Build Coastguard Worker    return [dict(zip(dict_keys, value_combination))
709*a65addddSAndroid Build Coastguard Worker            for value_combination in value_combinations]
710*a65addddSAndroid Build Coastguard Worker
711*a65addddSAndroid Build Coastguard Worker
712*a65addddSAndroid Build Coastguard Workerdef expand_benchmark_definitions(benchmark_definitions: List[Dict[str, Any]]):
713*a65addddSAndroid Build Coastguard Worker    return list(itertools.chain(*[expand_benchmark_definition(benchmark_definition) for benchmark_definition in benchmark_definitions]))
714*a65addddSAndroid Build Coastguard Worker
715*a65addddSAndroid Build Coastguard WorkerT = TypeVar('T')
716*a65addddSAndroid Build Coastguard WorkerK = TypeVar('K')
717*a65addddSAndroid Build Coastguard Worker
718*a65addddSAndroid Build Coastguard Workerdef group_by(l: List[T], element_to_key: Callable[[T], K]) -> Iterable[Tuple[K, List[T]]]:
719*a65addddSAndroid Build Coastguard Worker    """Takes a list and returns a list of sublists, where the elements are grouped using the provided function"""
720*a65addddSAndroid Build Coastguard Worker    result = defaultdict(list)  # type: Dict[K, List[T]]
721*a65addddSAndroid Build Coastguard Worker    for elem in l:
722*a65addddSAndroid Build Coastguard Worker        result[element_to_key(elem)].append(elem)
723*a65addddSAndroid Build Coastguard Worker    return result.items()
724*a65addddSAndroid Build Coastguard Worker
725*a65addddSAndroid Build Coastguard Workerdef main():
726*a65addddSAndroid Build Coastguard Worker    # This configures numpy/scipy to raise an exception in case of errors, instead of printing a warning and going ahead.
727*a65addddSAndroid Build Coastguard Worker    numpy.seterr(all='raise')
728*a65addddSAndroid Build Coastguard Worker    scipy.seterr(all='raise')
729*a65addddSAndroid Build Coastguard Worker
730*a65addddSAndroid Build Coastguard Worker    parser = argparse.ArgumentParser(description='Runs a set of benchmarks defined in a YAML file.')
731*a65addddSAndroid Build Coastguard Worker    parser.add_argument('--fruit-benchmark-sources-dir', help='Path to the fruit sources (used for benchmarking code only)')
732*a65addddSAndroid Build Coastguard Worker    parser.add_argument('--fruit-sources-dir', help='Path to the fruit sources')
733*a65addddSAndroid Build Coastguard Worker    parser.add_argument('--boost-di-sources-dir', help='Path to the Boost.DI sources')
734*a65addddSAndroid Build Coastguard Worker    parser.add_argument('--output-file',
735*a65addddSAndroid Build Coastguard Worker                        help='The output file where benchmark results will be stored (1 per line, with each line in JSON format). These can then be formatted by e.g. the format_bench_results script.')
736*a65addddSAndroid Build Coastguard Worker    parser.add_argument('--benchmark-definition', help='The YAML file that defines the benchmarks (see fruit_wiki_benchs_fruit.yml for an example).')
737*a65addddSAndroid Build Coastguard Worker    parser.add_argument('--continue-benchmark', help='If this is \'true\', continues a previous benchmark run instead of starting from scratch (taking into account the existing benchmark results in the file specified with --output-file).')
738*a65addddSAndroid Build Coastguard Worker    args = parser.parse_args()
739*a65addddSAndroid Build Coastguard Worker
740*a65addddSAndroid Build Coastguard Worker    if args.output_file is None:
741*a65addddSAndroid Build Coastguard Worker        raise Exception('You must specify --output_file')
742*a65addddSAndroid Build Coastguard Worker    if args.continue_benchmark == 'true':
743*a65addddSAndroid Build Coastguard Worker        try:
744*a65addddSAndroid Build Coastguard Worker            with open(args.output_file, 'r') as f:
745*a65addddSAndroid Build Coastguard Worker                previous_run_completed_benchmarks = [json.loads(line)['benchmark'] for line in f.readlines()]
746*a65addddSAndroid Build Coastguard Worker        except FileNotFoundError:
747*a65addddSAndroid Build Coastguard Worker            previous_run_completed_benchmarks = []
748*a65addddSAndroid Build Coastguard Worker    else:
749*a65addddSAndroid Build Coastguard Worker        previous_run_completed_benchmarks = []
750*a65addddSAndroid Build Coastguard Worker        run_command('rm', args=['-f', args.output_file])
751*a65addddSAndroid Build Coastguard Worker
752*a65addddSAndroid Build Coastguard Worker    fruit_build_dir = tempfile.gettempdir() + '/fruit-benchmark-build-dir'
753*a65addddSAndroid Build Coastguard Worker
754*a65addddSAndroid Build Coastguard Worker    with open(args.benchmark_definition, 'r') as f:
755*a65addddSAndroid Build Coastguard Worker        yaml_file_content = yaml.full_load(f)
756*a65addddSAndroid Build Coastguard Worker        global_definitions = yaml_file_content['global']
757*a65addddSAndroid Build Coastguard Worker        benchmark_definitions = expand_benchmark_definitions(yaml_file_content['benchmarks'])
758*a65addddSAndroid Build Coastguard Worker
759*a65addddSAndroid Build Coastguard Worker    benchmark_index = 0
760*a65addddSAndroid Build Coastguard Worker
761*a65addddSAndroid Build Coastguard Worker    for (compiler_executable_name, additional_cmake_args), benchmark_definitions_with_current_config \
762*a65addddSAndroid Build Coastguard Worker            in group_by(benchmark_definitions,
763*a65addddSAndroid Build Coastguard Worker                        lambda benchmark_definition:
764*a65addddSAndroid Build Coastguard Worker                            (benchmark_definition['compiler'], tuple(benchmark_definition['additional_cmake_args']))):
765*a65addddSAndroid Build Coastguard Worker
766*a65addddSAndroid Build Coastguard Worker        print('Preparing for benchmarks with the compiler %s, with additional CMake args %s' % (compiler_executable_name, additional_cmake_args))
767*a65addddSAndroid Build Coastguard Worker        try:
768*a65addddSAndroid Build Coastguard Worker            # We compute this here (and memoize the result) so that the benchmark's describe() will retrieve the cached
769*a65addddSAndroid Build Coastguard Worker            # value instantly.
770*a65addddSAndroid Build Coastguard Worker            determine_compiler_name(compiler_executable_name)
771*a65addddSAndroid Build Coastguard Worker
772*a65addddSAndroid Build Coastguard Worker            # Build Fruit in fruit_build_dir, so that fruit_build_dir points to a built Fruit (useful for e.g. the config header).
773*a65addddSAndroid Build Coastguard Worker            shutil.rmtree(fruit_build_dir, ignore_errors=True)
774*a65addddSAndroid Build Coastguard Worker            os.makedirs(fruit_build_dir)
775*a65addddSAndroid Build Coastguard Worker            modified_env = os.environ.copy()
776*a65addddSAndroid Build Coastguard Worker            modified_env['CXX'] = compiler_executable_name
777*a65addddSAndroid Build Coastguard Worker            run_command('cmake',
778*a65addddSAndroid Build Coastguard Worker                        args=[
779*a65addddSAndroid Build Coastguard Worker                            args.fruit_sources_dir,
780*a65addddSAndroid Build Coastguard Worker                            '-DCMAKE_BUILD_TYPE=Release',
781*a65addddSAndroid Build Coastguard Worker                            *additional_cmake_args,
782*a65addddSAndroid Build Coastguard Worker                        ],
783*a65addddSAndroid Build Coastguard Worker                        cwd=fruit_build_dir,
784*a65addddSAndroid Build Coastguard Worker                        env=modified_env)
785*a65addddSAndroid Build Coastguard Worker            run_command('make', args=make_args, cwd=fruit_build_dir)
786*a65addddSAndroid Build Coastguard Worker        except Exception as e:
787*a65addddSAndroid Build Coastguard Worker            print('Exception while preparing for benchmarks with the compiler %s, with additional CMake args %s.\n%s\nGoing ahead with the rest.' % (compiler_executable_name, additional_cmake_args, traceback.format_exc()))
788*a65addddSAndroid Build Coastguard Worker            continue
789*a65addddSAndroid Build Coastguard Worker
790*a65addddSAndroid Build Coastguard Worker        for benchmark_definition in benchmark_definitions_with_current_config:
791*a65addddSAndroid Build Coastguard Worker            benchmark_index += 1
792*a65addddSAndroid Build Coastguard Worker            print('%s/%s: %s' % (benchmark_index, len(benchmark_definitions), benchmark_definition))
793*a65addddSAndroid Build Coastguard Worker            benchmark_name = benchmark_definition['name']
794*a65addddSAndroid Build Coastguard Worker
795*a65addddSAndroid Build Coastguard Worker            if (benchmark_name in {'boost_di_compile_time', 'boost_di_run_time', 'boost_di_executable_size'}
796*a65addddSAndroid Build Coastguard Worker                    and args.boost_di_sources_dir is None):
797*a65addddSAndroid Build Coastguard Worker                raise Exception('Error: you need to specify the --boost-di-sources-dir flag in order to run Boost.DI benchmarks.')
798*a65addddSAndroid Build Coastguard Worker
799*a65addddSAndroid Build Coastguard Worker            if benchmark_name == 'new_delete_run_time':
800*a65addddSAndroid Build Coastguard Worker                benchmark = SimpleNewDeleteRunTimeBenchmark(
801*a65addddSAndroid Build Coastguard Worker                    benchmark_definition,
802*a65addddSAndroid Build Coastguard Worker                    fruit_benchmark_sources_dir=args.fruit_benchmark_sources_dir)
803*a65addddSAndroid Build Coastguard Worker            elif benchmark_name == 'fruit_single_file_compile_time':
804*a65addddSAndroid Build Coastguard Worker                benchmark = FruitSingleFileCompileTimeBenchmark(
805*a65addddSAndroid Build Coastguard Worker                    benchmark_definition,
806*a65addddSAndroid Build Coastguard Worker                    fruit_sources_dir=args.fruit_sources_dir,
807*a65addddSAndroid Build Coastguard Worker                    fruit_benchmark_sources_dir=args.fruit_benchmark_sources_dir,
808*a65addddSAndroid Build Coastguard Worker                    fruit_build_dir=fruit_build_dir)
809*a65addddSAndroid Build Coastguard Worker            elif benchmark_name.startswith('fruit_'):
810*a65addddSAndroid Build Coastguard Worker                benchmark_class = {
811*a65addddSAndroid Build Coastguard Worker                    'fruit_compile_time': FruitCompileTimeBenchmark,
812*a65addddSAndroid Build Coastguard Worker                    'fruit_incremental_compile_time': FruitIncrementalCompileTimeBenchmark,
813*a65addddSAndroid Build Coastguard Worker                    'fruit_compile_memory': FruitCompileMemoryBenchmark,
814*a65addddSAndroid Build Coastguard Worker                    'fruit_run_time': FruitRunTimeBenchmark,
815*a65addddSAndroid Build Coastguard Worker                    'fruit_startup_time': FruitStartupTimeBenchmark,
816*a65addddSAndroid Build Coastguard Worker                    'fruit_startup_time_with_normalized_component': FruitStartupTimeWithNormalizedComponentBenchmark,
817*a65addddSAndroid Build Coastguard Worker                    'fruit_executable_size': FruitExecutableSizeBenchmark,
818*a65addddSAndroid Build Coastguard Worker                    'fruit_executable_size_without_exceptions_and_rtti': FruitExecutableSizeBenchmarkWithoutExceptionsAndRtti,
819*a65addddSAndroid Build Coastguard Worker                }[benchmark_name]
820*a65addddSAndroid Build Coastguard Worker                benchmark = benchmark_class(
821*a65addddSAndroid Build Coastguard Worker                    benchmark_definition=benchmark_definition,
822*a65addddSAndroid Build Coastguard Worker                    fruit_sources_dir=args.fruit_sources_dir,
823*a65addddSAndroid Build Coastguard Worker                    fruit_build_dir=fruit_build_dir)
824*a65addddSAndroid Build Coastguard Worker            elif benchmark_name.startswith('boost_di_'):
825*a65addddSAndroid Build Coastguard Worker                benchmark_class = {
826*a65addddSAndroid Build Coastguard Worker                    'boost_di_compile_time': BoostDiCompileTimeBenchmark,
827*a65addddSAndroid Build Coastguard Worker                    'boost_di_incremental_compile_time': BoostDiIncrementalCompileTimeBenchmark,
828*a65addddSAndroid Build Coastguard Worker                    'boost_di_compile_memory': BoostDiCompileMemoryBenchmark,
829*a65addddSAndroid Build Coastguard Worker                    'boost_di_run_time': BoostDiRunTimeBenchmark,
830*a65addddSAndroid Build Coastguard Worker                    'boost_di_startup_time': BoostDiStartupTimeBenchmark,
831*a65addddSAndroid Build Coastguard Worker                    'boost_di_executable_size': BoostDiExecutableSizeBenchmark,
832*a65addddSAndroid Build Coastguard Worker                    'boost_di_executable_size_without_exceptions_and_rtti': BoostDiExecutableSizeBenchmarkWithoutExceptionsAndRtti,
833*a65addddSAndroid Build Coastguard Worker                }[benchmark_name]
834*a65addddSAndroid Build Coastguard Worker                benchmark = benchmark_class(
835*a65addddSAndroid Build Coastguard Worker                    benchmark_definition=benchmark_definition,
836*a65addddSAndroid Build Coastguard Worker                    boost_di_sources_dir=args.boost_di_sources_dir)
837*a65addddSAndroid Build Coastguard Worker            elif benchmark_name.startswith('simple_di_'):
838*a65addddSAndroid Build Coastguard Worker                benchmark_class = {
839*a65addddSAndroid Build Coastguard Worker                    'simple_di_compile_time': SimpleDiCompileTimeBenchmark,
840*a65addddSAndroid Build Coastguard Worker                    'simple_di_incremental_compile_time': SimpleDiIncrementalCompileTimeBenchmark,
841*a65addddSAndroid Build Coastguard Worker                    'simple_di_compile_memory': SimpleDiCompileMemoryBenchmark,
842*a65addddSAndroid Build Coastguard Worker                    'simple_di_run_time': SimpleDiRunTimeBenchmark,
843*a65addddSAndroid Build Coastguard Worker                    'simple_di_startup_time': SimpleDiStartupTimeBenchmark,
844*a65addddSAndroid Build Coastguard Worker                    'simple_di_executable_size': SimpleDiExecutableSizeBenchmark,
845*a65addddSAndroid Build Coastguard Worker                    'simple_di_executable_size_without_exceptions_and_rtti': SimpleDiExecutableSizeBenchmarkWithoutExceptionsAndRtti,
846*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_compile_time': SimpleDiWithInterfacesCompileTimeBenchmark,
847*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_incremental_compile_time': SimpleDiWithInterfacesIncrementalCompileTimeBenchmark,
848*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_compile_memory': SimpleDiWithInterfacesCompileMemoryBenchmark,
849*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_run_time': SimpleDiWithInterfacesRunTimeBenchmark,
850*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_startup_time': SimpleDiWithInterfacesStartupTimeBenchmark,
851*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_executable_size': SimpleDiWithInterfacesExecutableSizeBenchmark,
852*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_executable_size_without_exceptions_and_rtti': SimpleDiWithInterfacesExecutableSizeBenchmarkWithoutExceptionsAndRtti,
853*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_and_new_delete_compile_time': SimpleDiWithInterfacesAndNewDeleteCompileTimeBenchmark,
854*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_and_new_delete_incremental_compile_time': SimpleDiWithInterfacesAndNewDeleteIncrementalCompileTimeBenchmark,
855*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_and_new_delete_compile_memory': SimpleDiWithInterfacesAndNewDeleteCompileMemoryBenchmark,
856*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_and_new_delete_run_time': SimpleDiWithInterfacesAndNewDeleteRunTimeBenchmark,
857*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_and_new_delete_startup_time': SimpleDiWithInterfacesAndNewDeleteStartupTimeBenchmark,
858*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_and_new_delete_executable_size': SimpleDiWithInterfacesAndNewDeleteExecutableSizeBenchmark,
859*a65addddSAndroid Build Coastguard Worker                    'simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti': SimpleDiWithInterfacesAndNewDeleteExecutableSizeBenchmarkWithoutExceptionsAndRtti,
860*a65addddSAndroid Build Coastguard Worker                }[benchmark_name]
861*a65addddSAndroid Build Coastguard Worker                benchmark = benchmark_class(
862*a65addddSAndroid Build Coastguard Worker                    benchmark_definition=benchmark_definition)
863*a65addddSAndroid Build Coastguard Worker            else:
864*a65addddSAndroid Build Coastguard Worker                raise Exception("Unrecognized benchmark: %s" % benchmark_name)
865*a65addddSAndroid Build Coastguard Worker
866*a65addddSAndroid Build Coastguard Worker            if benchmark.describe() in previous_run_completed_benchmarks:
867*a65addddSAndroid Build Coastguard Worker                print("Skipping benchmark that was already run previously (due to --continue-benchmark):", benchmark.describe())
868*a65addddSAndroid Build Coastguard Worker                continue
869*a65addddSAndroid Build Coastguard Worker
870*a65addddSAndroid Build Coastguard Worker            try:
871*a65addddSAndroid Build Coastguard Worker                run_benchmark(benchmark,
872*a65addddSAndroid Build Coastguard Worker                            output_file=args.output_file,
873*a65addddSAndroid Build Coastguard Worker                            max_runs=global_definitions['max_runs'],
874*a65addddSAndroid Build Coastguard Worker                            timeout_hours=global_definitions['max_hours_per_combination'])
875*a65addddSAndroid Build Coastguard Worker            except Exception as e:
876*a65addddSAndroid Build Coastguard Worker                print('Exception while running benchmark: %s.\n%s\nGoing ahead with the rest.' % (benchmark.describe(), traceback.format_exc()))
877*a65addddSAndroid Build Coastguard Worker
878*a65addddSAndroid Build Coastguard Worker
879*a65addddSAndroid Build Coastguard Workerif __name__ == "__main__":
880*a65addddSAndroid Build Coastguard Worker    main()
881