Beispiel #1
0
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))
Beispiel #2
0
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()
Beispiel #3
0
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()