Skip to content

Commit

Permalink
Added a tool to help benchmark FakeIt compilation speed.
Browse files Browse the repository at this point in the history
  • Loading branch information
FranckRJ committed May 26, 2024
1 parent c1d74ea commit e2778fa
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ build/

# Testing
Testing/

# Benchmark
benchmark/bench*
15 changes: 15 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
First create the benchmark files:
```bash
python3 create_benchmark.py bench/
```
_Note: you can check the help of the script for additional options._

Then generate the build files:
```bash
cmake -S bench/ -B bench/build -DCMAKE_BUILD_TYPE=Debug
```

Then build with a tool that helps you time the build, like the linux command `time`:
```bash
time cmake --build bench/build -j
```
140 changes: 140 additions & 0 deletions benchmark/create_benchmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse
import os
import pathlib
from dataclasses import dataclass

fakeit_path = os.path.join(os.path.dirname(__file__), "..")


@dataclass
class ProjectStructure:
gen_dir: os.PathLike
single_header_dir: os.PathLike
files: int
interfaces: int
methods: int
stubs: int


def create_project(project_structure: ProjectStructure):
pathlib.Path(project_structure.gen_dir).mkdir(parents=True, exist_ok=True)
# Test file
for file_idx in range(0, project_structure.files):
with open(
os.path.join(project_structure.gen_dir, f"file_{file_idx}.cpp"), "w"
) as file:
file.write("#include <fakeit.hpp>\n")
file.write(f'#include "file_{file_idx}.hpp"\n')
file.write("using namespace fakeit;\n")
file.write("namespace {\n")
# Interface
for interface_idx in range(0, project_structure.interfaces):
file.write(f"class Interface_{interface_idx} {{\n")
file.write("public:\n")
# Method
for method_idx in range(0, project_structure.methods):
file.write(f" virtual int method_{method_idx}(int) = 0;\n")
file.write("};\n")
# Test of methods
file.write(f"void test_interface_{interface_idx}() {{\n")
file.write(f" Mock<Interface_{interface_idx}> mock;\n")
for method_idx in range(0, project_structure.methods):
for stub_idx in range(0, project_structure.stubs):
file.write(
f" When(Method(mock, method_{method_idx}).Using({stub_idx})).Return({stub_idx});\n"
)
for method_idx in range(0, project_structure.methods):
for stub_idx in range(0, project_structure.stubs):
file.write(f" mock.get().method_{method_idx}({stub_idx});\n")
for method_idx in range(0, project_structure.methods):
for stub_idx in range(0, project_structure.stubs):
file.write(
f" Verify(Method(mock, method_{method_idx}).Using({stub_idx})).Exactly(1);\n"
)
file.write("}\n")
file.write("}\n")
# Test of whole file
file.write(f"void test_file_{file_idx}() {{\n")
for interface_idx in range(0, project_structure.interfaces):
file.write(f" test_interface_{interface_idx}();\n")
file.write("}\n")
# Header of test file
with open(
os.path.join(project_structure.gen_dir, f"file_{file_idx}.hpp"), "w"
) as file:
file.write("#pragma once\n")
file.write(f"void test_file_{file_idx}();\n")
# Main
with open(os.path.join(project_structure.gen_dir, "main.cpp"), "w") as file:
for file_idx in range(0, project_structure.files):
file.write(f'#include "file_{file_idx}.hpp"\n')
file.write("int main() {\n")
for file_idx in range(0, project_structure.files):
file.write(f" test_file_{file_idx}();\n")
file.write("}\n")
# CMake file
with open(os.path.join(project_structure.gen_dir, "CMakeLists.txt"), "w") as file:
file.write("cmake_minimum_required(VERSION 3.14)\n")
file.write("project(FakeIt-bench LANGUAGES CXX)\n")
file.write("add_executable(bench\n")
for file_idx in range(0, project_structure.files):
file.write(f" file_{file_idx}.cpp\n")
file.write(f" main.cpp\n")
file.write(")\n")
file.write(
f'target_include_directories(bench PRIVATE "{project_structure.single_header_dir}")\n'
)


def get_parser():
parser = argparse.ArgumentParser()
parser.add_argument(
"directory",
type=str,
help="Directory where the benchmark project will be created.",
)
parser.add_argument(
"-d",
"--header-dir",
type=str,
default=os.path.join(fakeit_path, "single_header", "standalone"),
help="The directory containing the fakeit single header.",
)
parser.add_argument(
"-f", "--files", type=int, default=10, help="Number of C++ files to create."
)
parser.add_argument(
"-i",
"--interfaces",
type=int,
default=10,
help="Number of interfaces per file.",
)
parser.add_argument(
"-m", "--methods", type=int, default=10, help="Number of methods per interface."
)
parser.add_argument(
"-s", "--stubs", type=int, default=10, help="Number of stubs per methods."
)
return parser


def main():
args = get_parser().parse_args()
create_project(
ProjectStructure(
args.directory,
args.header_dir,
args.files,
args.interfaces,
args.methods,
args.stubs,
)
)


if __name__ == "__main__":
main()

0 comments on commit e2778fa

Please sign in to comment.