def generate_benchmark( di_library, compiler, cxx_std, fruit_build_dir, fruit_sources_dir, output_dir, num_components_with_no_deps, num_components_with_deps, num_deps, boost_di_sources_dir=None, use_old_style_fruit_component_install_syntax=False, generate_debuginfo=False): """Generates a sample codebase using the specified DI library, meant for benchmarking. :param boost_di_sources_dir: this is only used if di_library=='boost_di', it can be None otherwise. """ if num_components_with_no_deps < num_deps: raise Exception( "Too few components with no deps. num_components_with_no_deps=%s but num_deps=%s." % (num_components_with_no_deps, num_deps)) if num_deps < 2: raise Exception("num_deps should be at least 2.") # This is a constant so that we always generate the same file (=> benchmark more repeatable). random.seed(42) if di_library == 'fruit': source_generator = FruitSourceGenerator( use_old_style_component_install_syntax = use_old_style_fruit_component_install_syntax) include_dirs = [fruit_build_dir + '/include', fruit_sources_dir + '/include'] library_dirs = [fruit_build_dir + '/src'] link_libraries = ['fruit'] elif di_library == 'boost_di': source_generator = BoostDiSourceGenerator() include_dirs = [boost_di_sources_dir + '/include'] library_dirs = [] link_libraries = [] else: raise Exception('Unrecognized di_library: %s' % di_library) os.makedirs(output_dir, exist_ok=True) num_used_ids = 0 is_toplevel = [True for i in range(0, num_components_with_no_deps + num_components_with_deps)] toplevel_components = set() for i in range(0, num_components_with_no_deps): id = num_used_ids num_used_ids += 1 add_node(id, [], source_generator=source_generator, output_dir=output_dir) toplevel_components |= {id} # Then the rest have num_deps deps, chosen (pseudo-)randomly from the previous components with no # deps, plus the previous component with deps (if any). # However, the last few components depend on multiple components with >1 deps, so that the last # component transitively depends on everything. for i in range(0, num_components_with_deps): deps = set() if len(toplevel_components) > (num_components_with_deps - 1 - i) * (num_deps - 1): # We need at least 1 dep with deps, otherwise the last few components will not be enough # to tie together all components. num_deps_with_deps = len(toplevel_components) - (num_components_with_deps - 1 - i) * (num_deps - 1) deps |= set(random.sample(toplevel_components, num_deps_with_deps)) if i != 0 and len(deps) < num_deps: # Pick one random component with deps. # If we picked num_deps random components here, the computation of the n-th component (during # the benchmark) would take time super-linear in n, and we don't want that (if most time was # spent constructing the component rather than constructing the injector and injecting objects, # the benchmark would be slow and not very meaningful). deps |= {num_components_with_no_deps + random.randint(0, i - 1)} # Add other deps with no deps to get to the desired num_deps. deps |= set(random.sample(range(0, num_components_with_no_deps), num_deps - len(deps))) toplevel_components -= deps for dep in deps: is_toplevel[dep] = False component_id = num_used_ids toplevel_components |= {component_id} num_used_ids += 1 deps_list = list(deps) random.shuffle(deps_list) add_node(component_id, deps_list, source_generator, output_dir=output_dir) assert len(toplevel_components) == 1, toplevel_components toplevel_component = num_used_ids - 1 assert is_toplevel[toplevel_component] with open("%s/main.cpp" % output_dir, 'w') as mainFile: mainFile.write(source_generator.generate_main(toplevel_component)) include_flags = ' '.join(['-I%s' % include_dir for include_dir in include_dirs]) library_dirs_flags = ' '.join(['-L%s' % library_dir for library_dir in library_dirs]) rpath_flags = ' '.join(['-Wl,-rpath,%s' % library_dir for library_dir in library_dirs]) link_libraries_flags = ' '.join(['-l%s' % library for library in link_libraries]) other_compile_flags = [] if use_old_style_fruit_component_install_syntax: other_compile_flags.append('-Wno-deprecated-declarations') if generate_debuginfo: other_compile_flags.append('-g') compile_command = '%s -std=%s -O2 -W -Wall -Werror -DNDEBUG -ftemplate-depth=1000 %s %s' % (compiler, cxx_std, include_flags, ' '.join(other_compile_flags)) link_command = '%s -std=%s -O2 -W -Wall -Werror %s %s' % (compiler, cxx_std, rpath_flags, library_dirs_flags) # GCC requires passing the -lfruit flag *after* all object files to be linked for some reason. link_command_suffix = link_libraries_flags sources = ['component%s' % i for i in range(0, num_used_ids)] sources += ['main'] with open("%s/Makefile" % output_dir, 'w') as makefile: makefile.write(generate_makefile(sources, 'main', compile_command, link_command, link_command_suffix))
def generate_benchmark(di_library: str, compiler: str, cxx_std: str, output_dir: str, num_components_with_no_deps: int, num_components_with_deps: int, num_deps: int, generate_runtime_bench_code: bool, use_exceptions: bool = True, use_rtti: bool = True, fruit_build_dir: str = None, fruit_sources_dir: str = None, boost_di_sources_dir: str = None, generate_debuginfo: bool = False, use_new_delete: bool = False, use_interfaces: bool = False, use_normalized_component: bool = False): """Generates a sample codebase using the specified DI library, meant for benchmarking. :param boost_di_sources_dir: this is only used if di_library=='boost_di', it can be None otherwise. """ if num_components_with_no_deps < num_deps: raise Exception( "Too few components with no deps. num_components_with_no_deps=%s but num_deps=%s." % (num_components_with_no_deps, num_deps)) if num_deps < 2: raise Exception("num_deps should be at least 2.") # This is a constant so that we always generate the same file (=> benchmark more repeatable). random.seed(42) injection_graph = generate_injection_graph( num_components_with_no_deps=num_components_with_no_deps, num_components_with_deps=num_components_with_deps, num_deps=num_deps) if di_library == 'fruit': file_content_by_name = fruit_source_generator.generate_files( injection_graph, generate_runtime_bench_code) include_dirs = [ fruit_build_dir + '/include', fruit_sources_dir + '/include' ] library_dirs = [fruit_build_dir + '/src'] link_libraries = ['fruit'] elif di_library == 'boost_di': file_content_by_name = boost_di_source_generator.generate_files( injection_graph, generate_runtime_bench_code) include_dirs = [ boost_di_sources_dir + '/include', boost_di_sources_dir + '/extension/include' ] library_dirs = [] link_libraries = [] elif di_library == 'none': file_content_by_name = no_di_library_source_generator.generate_files( injection_graph, use_new_delete, use_interfaces, generate_runtime_bench_code) include_dirs = [] library_dirs = [] link_libraries = [] else: raise Exception('Unrecognized di_library: %s' % di_library) include_flags = ' '.join( ['-I%s' % include_dir for include_dir in include_dirs]) library_dirs_flags = ' '.join( ['-L%s' % library_dir for library_dir in library_dirs]) rpath_flags = ' '.join( ['-Wl,-rpath,%s' % library_dir for library_dir in library_dirs]) link_libraries_flags = ' '.join( ['-l%s' % library for library in link_libraries]) other_compile_flags = [] if generate_debuginfo: other_compile_flags.append('-g') if not use_exceptions: other_compile_flags.append('-fno-exceptions') if not use_rtti: other_compile_flags.append('-fno-rtti') compile_command = '%s -std=%s -MMD -MP -O2 -W -Wall -DNDEBUG -ftemplate-depth=10000 %s %s' % ( compiler, cxx_std, include_flags, ' '.join(other_compile_flags)) link_command = '%s -std=%s -O2 -W -Wall %s %s' % ( compiler, cxx_std, rpath_flags, library_dirs_flags) # GCC requires passing the -lfruit flag *after* all object files to be linked for some reason. link_command_suffix = link_libraries_flags cpp_files = [ file_name for file_name in file_content_by_name.keys() if file_name.endswith('.cpp') ] file_content_by_name['Makefile'] = generate_makefile( cpp_files, 'main', compile_command, link_command, link_command_suffix) os.makedirs(output_dir, exist_ok=True) for file_name, file_content in file_content_by_name.items(): with open('%s/%s' % (output_dir, file_name), 'w') as file: file.write(file_content) return file_content_by_name.keys()
def generate_benchmark( di_library, compiler, cxx_std, output_dir, num_components_with_no_deps, num_components_with_deps, num_deps, generate_runtime_bench_code, use_exceptions=True, use_rtti=True, fruit_build_dir=None, fruit_sources_dir=None, boost_di_sources_dir=None, generate_debuginfo=False, use_new_delete=False, use_interfaces=False, use_normalized_component=False): """Generates a sample codebase using the specified DI library, meant for benchmarking. :param boost_di_sources_dir: this is only used if di_library=='boost_di', it can be None otherwise. """ if num_components_with_no_deps < num_deps: raise Exception( "Too few components with no deps. num_components_with_no_deps=%s but num_deps=%s." % (num_components_with_no_deps, num_deps)) if num_deps < 2: raise Exception("num_deps should be at least 2.") # This is a constant so that we always generate the same file (=> benchmark more repeatable). random.seed(42) injection_graph = generate_injection_graph(num_components_with_no_deps=num_components_with_no_deps, num_components_with_deps=num_components_with_deps, num_deps=num_deps) if di_library == 'fruit': file_content_by_name = fruit_source_generator.generate_files(injection_graph, generate_runtime_bench_code) include_dirs = [fruit_build_dir + '/include', fruit_sources_dir + '/include'] library_dirs = [fruit_build_dir + '/src'] link_libraries = ['fruit'] elif di_library == 'boost_di': file_content_by_name = boost_di_source_generator.generate_files(injection_graph, generate_runtime_bench_code) include_dirs = [boost_di_sources_dir + '/include', boost_di_sources_dir + '/extension/include'] library_dirs = [] link_libraries = [] elif di_library == 'none': file_content_by_name = no_di_library_source_generator.generate_files(injection_graph, use_new_delete, use_interfaces, generate_runtime_bench_code) include_dirs = [] library_dirs = [] link_libraries = [] else: raise Exception('Unrecognized di_library: %s' % di_library) include_flags = ' '.join(['-I%s' % include_dir for include_dir in include_dirs]) library_dirs_flags = ' '.join(['-L%s' % library_dir for library_dir in library_dirs]) rpath_flags = ' '.join(['-Wl,-rpath,%s' % library_dir for library_dir in library_dirs]) link_libraries_flags = ' '.join(['-l%s' % library for library in link_libraries]) other_compile_flags = [] if generate_debuginfo: other_compile_flags.append('-g') if not use_exceptions: other_compile_flags.append('-fno-exceptions') if not use_rtti: other_compile_flags.append('-fno-rtti') compile_command = '%s -std=%s -MMD -MP -O2 -W -Wall -Werror -DNDEBUG -ftemplate-depth=10000 %s %s' % (compiler, cxx_std, include_flags, ' '.join(other_compile_flags)) link_command = '%s -std=%s -O2 -W -Wall -Werror %s %s' % (compiler, cxx_std, rpath_flags, library_dirs_flags) # GCC requires passing the -lfruit flag *after* all object files to be linked for some reason. link_command_suffix = link_libraries_flags cpp_files = [file_name for file_name in file_content_by_name.keys() if file_name.endswith('.cpp')] file_content_by_name['Makefile'] = generate_makefile(cpp_files, 'main', compile_command, link_command, link_command_suffix) os.makedirs(output_dir, exist_ok=True) for file_name, file_content in file_content_by_name.items(): with open('%s/%s' % (output_dir, file_name), 'w') as file: file.write(file_content) return file_content_by_name.keys()