Skip to content

Commit 266512c

Browse files
authored
🏁🏎 Improve compilation performance by replacing std::tuple with custom types. (#23)
resolves #13 - the big_nexus.cpp compilation performance test case is added to stress the library's template metaprogramming - optimized template metaprogramming constructs added to significantly improve compile time performance - additional versions of clang and gcc added
1 parent 75ca3b9 commit 266512c

21 files changed

+1004
-110
lines changed

.github/workflows/unit_tests.yml

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,52 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
include:
19+
- compiler: clang-14
20+
install: wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 14
21+
cc: " /usr/lib/llvm-14/bin/clang"
22+
cxx: "/usr/lib/llvm-14/bin/clang++"
23+
- compiler: clang-13
24+
install: wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 13
25+
cc: " /usr/lib/llvm-13/bin/clang"
26+
cxx: "/usr/lib/llvm-13/bin/clang++"
1927
- compiler: clang-12
28+
install: sudo apt update && sudo apt-get install -y clang-12
2029
cc: " /usr/lib/llvm-12/bin/clang"
2130
cxx: "/usr/lib/llvm-12/bin/clang++"
2231
- compiler: clang-11
32+
install: sudo apt update && sudo apt-get install -y clang-11
2333
cc: " /usr/lib/llvm-11/bin/clang"
2434
cxx: "/usr/lib/llvm-11/bin/clang++"
2535
- compiler: clang-10
36+
install: sudo apt update && sudo apt-get install -y clang-10
2637
cc: " /usr/lib/llvm-10/bin/clang"
2738
cxx: "/usr/lib/llvm-10/bin/clang++"
2839
- compiler: clang-9
40+
install: sudo apt update && sudo apt-get install -y clang-9
2941
cc: " /usr/lib/llvm-9/bin/clang"
3042
cxx: "/usr/lib/llvm-9/bin/clang++"
3143
- compiler: clang-8
44+
install: sudo apt update && sudo apt-get install -y clang-8
3245
cc: " /usr/lib/llvm-8/bin/clang"
3346
cxx: "/usr/lib/llvm-8/bin/clang++"
3447
- compiler: clang-7
48+
install: sudo apt update && sudo apt-get install -y clang-7
3549
cc: " /usr/lib/llvm-7/bin/clang"
3650
cxx: "/usr/lib/llvm-7/bin/clang++"
51+
- compiler: gcc-11
52+
install: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test && sudo apt update && sudo apt-get install -y gcc-11 g++-11
53+
cc: "/usr/bin/gcc-11"
54+
cxx: "/usr/bin/g++-11"
3755
- compiler: gcc-10
56+
install: sudo apt update && sudo apt-get install -y gcc-10
3857
cc: "/usr/bin/gcc-10"
3958
cxx: "/usr/bin/g++-10"
4059
- compiler: gcc-9
60+
install: sudo apt update && sudo apt-get install -y gcc-9
4161
cc: "/usr/bin/gcc-9"
4262
cxx: "/usr/bin/g++-9"
43-
- compiler: gcc-8 g++-8
63+
- compiler: gcc-8
64+
install: sudo apt update && sudo apt-get install -y gcc-8 g++-8
4465
cc: "/usr/bin/gcc-8"
4566
cxx: "/usr/bin/g++-8"
4667

@@ -50,28 +71,23 @@ jobs:
5071
submodules: recursive
5172

5273
- name: install compiler
53-
run: sudo apt update && sudo apt-get install -y ${{ matrix.compiler }}
74+
run: ${{ matrix.install }}
5475

5576
- name: Configure CMake
56-
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
57-
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
5877
env:
5978
CC: ${{ matrix.cc }}
6079
CXX: ${{ matrix.cxx }}
6180
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
6281

6382
- name: Build
64-
# Build your program with the given configuration
65-
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
83+
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -t tests
6684

6785
- name: Test
6886
working-directory: ${{github.workspace}}/build
69-
# Execute tests defined by the CMake configuration.
70-
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
7187
run: ctest -C ${{env.BUILD_TYPE}}
7288

89+
7390
build_single_header:
74-
needs: build_and_test
7591
runs-on: ubuntu-latest
7692
steps:
7793
- uses: actions/checkout@v3
@@ -91,5 +107,46 @@ jobs:
91107
name: cib.hpp
92108
path: build/cib.hpp
93109

110+
performance_test:
111+
runs-on: ubuntu-latest
112+
strategy:
113+
fail-fast: false
114+
115+
steps:
116+
- uses: actions/checkout@v3
117+
with:
118+
submodules: recursive
119+
120+
- name: install compiler
121+
run: sudo apt update && sudo apt-get install -y clang-12
122+
123+
- name: Configure CMake
124+
env:
125+
CC: clang-12
126+
CXX: clang++-12
127+
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
94128

129+
- name: Build
130+
id: build_step
131+
run: |
132+
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -t compilation_benchmark |& tee ${{github.workspace}}/build/compilation_output.log
133+
echo "::set-output name=compile_benchmark_time::"`grep "Clang front-end timer" ${{github.workspace}}/build/compilation_output.log | grep -o "^\s\+\S\+\s" | grep -o "\S\+"`
134+
135+
- name: Post compilation performance to pull rquest
136+
uses: actions/github-script@v5
137+
with:
138+
github-token: ${{secrets.GITHUB_TOKEN}}
139+
script: |
140+
github.rest.issues.createComment({
141+
issue_number: context.issue.number,
142+
owner: context.repo.owner,
143+
repo: context.repo.repo,
144+
body: '### ⏱ 🏁 big_nexus.cpp compilation benchmark took **${{ steps.build_step.outputs.compile_benchmark_time }}** seconds'
145+
})
146+
147+
- name: 'Upload Compilation Trace'
148+
uses: actions/upload-artifact@v3
149+
with:
150+
name: compilation_trace.json
151+
path: ${{github.workspace}}/build/benchmark/CMakeFiles/compilation_benchmark.dir/big_nexus.cpp.json
95152

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ enable_testing()
77

88
add_subdirectory(lib/Catch2)
99
add_subdirectory(test)
10+
add_subdirectory(benchmark)
1011

1112
add_library(Cib INTERFACE)
1213

benchmark/CMakeLists.txt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
project(compile_time_init_build)
3+
4+
set(CMAKE_CXX_STANDARD 17)
5+
6+
add_executable(compilation_benchmark
7+
big_nexus.cpp
8+
)
9+
10+
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
11+
target_compile_options(compilation_benchmark
12+
PRIVATE
13+
-ferror-limit=8
14+
-ftime-report
15+
-ftime-trace
16+
)
17+
18+
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
19+
target_compile_options(compilation_benchmark
20+
PRIVATE
21+
-fmax-errors=8
22+
-ftime-report
23+
)
24+
endif()
25+
26+
27+
target_compile_options(compilation_benchmark
28+
PRIVATE
29+
-ftemplate-backtrace-limit=0
30+
)
31+
32+
target_link_libraries(compilation_benchmark PRIVATE Cib)

benchmark/big_nexus.cpp

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#include <cib/cib.hpp>
2+
3+
4+
using cib::detail::int_;
5+
6+
7+
template<int Id>
8+
[[maybe_unused]] static bool is_callback_invoked = false;
9+
10+
template<int Id, typename... Args>
11+
struct TestCallback : public cib::callback_meta<Args...> {};
12+
13+
template<int Id>
14+
struct TestComponent {
15+
constexpr static auto offset = Id * 100;
16+
17+
constexpr static auto config =
18+
cib::config(
19+
cib::exports<
20+
TestCallback<0 + offset>,
21+
TestCallback<1 + offset>,
22+
TestCallback<2 + offset>,
23+
TestCallback<3 + offset>,
24+
TestCallback<4 + offset>,
25+
TestCallback<5 + offset>,
26+
TestCallback<6 + offset>,
27+
TestCallback<7 + offset>,
28+
TestCallback<8 + offset>,
29+
TestCallback<9 + offset>//,
30+
// TestCallback<10 + offset>,
31+
// TestCallback<11 + offset>,
32+
// TestCallback<12 + offset>,
33+
// TestCallback<13 + offset>,
34+
// TestCallback<14 + offset>,
35+
// TestCallback<15 + offset>,
36+
// TestCallback<16 + offset>,
37+
// TestCallback<17 + offset>,
38+
// TestCallback<18 + offset>,
39+
// TestCallback<19 + offset>
40+
>,
41+
42+
cib::extend<TestCallback<offset>>([](){
43+
is_callback_invoked<offset> = true;
44+
}),
45+
46+
cib::extend<TestCallback<offset>>([](){
47+
is_callback_invoked<offset> = true;
48+
}),
49+
50+
cib::extend<TestCallback<offset>>([](){
51+
is_callback_invoked<offset> = true;
52+
}),
53+
54+
cib::extend<TestCallback<offset>>([](){
55+
is_callback_invoked<offset> = true;
56+
}),
57+
58+
cib::extend<TestCallback<offset>>([](){
59+
is_callback_invoked<offset> = true;
60+
}),
61+
62+
cib::extend<TestCallback<offset>>([](){
63+
is_callback_invoked<offset> = true;
64+
}),
65+
66+
cib::extend<TestCallback<offset>>([](){
67+
is_callback_invoked<offset> = true;
68+
}),
69+
70+
cib::extend<TestCallback<offset>>([](){
71+
is_callback_invoked<offset> = true;
72+
}),
73+
74+
cib::extend<TestCallback<offset>>([](){
75+
is_callback_invoked<offset> = true;
76+
}),
77+
78+
cib::extend<TestCallback<offset>>([](){
79+
is_callback_invoked<offset> = true;
80+
})//,
81+
82+
// cib::extend<TestCallback<offset>>([](){
83+
// is_callback_invoked<offset> = true;
84+
// }),
85+
//
86+
// cib::extend<TestCallback<offset>>([](){
87+
// is_callback_invoked<offset> = true;
88+
// }),
89+
//
90+
// cib::extend<TestCallback<offset>>([](){
91+
// is_callback_invoked<offset> = true;
92+
// }),
93+
//
94+
// cib::extend<TestCallback<offset>>([](){
95+
// is_callback_invoked<offset> = true;
96+
// }),
97+
//
98+
// cib::extend<TestCallback<offset>>([](){
99+
// is_callback_invoked<offset> = true;
100+
// }),
101+
//
102+
// cib::extend<TestCallback<offset>>([](){
103+
// is_callback_invoked<offset> = true;
104+
// }),
105+
//
106+
// cib::extend<TestCallback<offset>>([](){
107+
// is_callback_invoked<offset> = true;
108+
// }),
109+
//
110+
// cib::extend<TestCallback<offset>>([](){
111+
// is_callback_invoked<offset> = true;
112+
// }),
113+
//
114+
// cib::extend<TestCallback<offset>>([](){
115+
// is_callback_invoked<offset> = true;
116+
// }),
117+
//
118+
// cib::extend<TestCallback<offset>>([](){
119+
// is_callback_invoked<offset> = true;
120+
// })
121+
);
122+
};
123+
124+
struct BigConfig {
125+
constexpr static auto config =
126+
cib::config(
127+
cib::components<
128+
cib::args<>,
129+
TestComponent<0>,
130+
TestComponent<1>,
131+
TestComponent<2>,
132+
TestComponent<3>,
133+
TestComponent<4>,
134+
TestComponent<5>,
135+
TestComponent<6>,
136+
TestComponent<7>,
137+
TestComponent<8>,
138+
TestComponent<9>,
139+
TestComponent<10>,
140+
TestComponent<11>,
141+
TestComponent<12>,
142+
TestComponent<13>,
143+
TestComponent<14>,
144+
TestComponent<15>,
145+
TestComponent<16>,
146+
TestComponent<17>,
147+
TestComponent<18>,
148+
TestComponent<19>//,
149+
// TestComponent<20>,
150+
// TestComponent<21>,
151+
// TestComponent<22>,
152+
// TestComponent<23>,
153+
// TestComponent<24>,
154+
// TestComponent<25>,
155+
// TestComponent<26>,
156+
// TestComponent<27>,
157+
// TestComponent<28>,
158+
// TestComponent<29>,
159+
// TestComponent<30>,
160+
// TestComponent<31>,
161+
// TestComponent<32>,
162+
// TestComponent<33>,
163+
// TestComponent<34>,
164+
// TestComponent<35>,
165+
// TestComponent<36>,
166+
// TestComponent<37>,
167+
// TestComponent<38>,
168+
// TestComponent<39>,
169+
// TestComponent<40>,
170+
// TestComponent<41>,
171+
// TestComponent<42>,
172+
// TestComponent<43>,
173+
// TestComponent<44>,
174+
// TestComponent<45>,
175+
// TestComponent<46>,
176+
// TestComponent<47>,
177+
// TestComponent<48>,
178+
// TestComponent<49>
179+
>
180+
);
181+
};
182+
183+
int main() {
184+
cib::nexus<BigConfig> nexus{};
185+
nexus.init();
186+
nexus.service<TestCallback<0>>();
187+
}

0 commit comments

Comments
 (0)