Skip to content

Commit 1801b1a

Browse files
authored
👷 Add benchmark to ci (#80)
Reduce generated_tests from 40 to 10 by stacking deeper runs within the benchmark.
1 parent 67b8b05 commit 1801b1a

20 files changed

Lines changed: 14749 additions & 44 deletions

.github/workflows/ci.yml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,25 @@ jobs:
4343
with:
4444
compiler_profile_url: https://github.com/libhal/arm-gnu-toolchain.git
4545
compiler_profile: v1/arm-gcc-12.3
46-
platform_profile_url: https://github.com/libhal/libhal-lpc40.git
47-
platform_profile: v2/lpc4078
46+
platform_profile_url: https://github.com/libhal/libhal-arm-mcu.git
47+
platform_profile: v1/lpc4078
4848
secrets: inherit
4949

5050
demo_check_stm32f103c8:
5151
uses: libhal/ci/.github/workflows/demo_builder.yml@5.x.y
5252
with:
5353
compiler_profile_url: https://github.com/libhal/arm-gnu-toolchain.git
5454
compiler_profile: v1/arm-gcc-12.3
55-
platform_profile_url: https://github.com/libhal/libhal-stm32f1.git
56-
platform_profile: v2/stm32f103c8
55+
platform_profile_url: https://github.com/libhal/libhal-arm-mcu.git
56+
platform_profile: v1/stm32f103c8
57+
secrets: inherit
58+
59+
build_benchmarks:
60+
uses: libhal/ci/.github/workflows/app_builder.yml@5.x.y
61+
with:
62+
compiler_profile_url: https://github.com/libhal/arm-gnu-toolchain.git
63+
compiler_profile: v1/arm-gcc-12.3
64+
platform_profile_url: https://github.com/libhal/libhal-arm-mcu.git
65+
platform_profile: v1/stm32f103c8
66+
conan_build_dir: benchmark
5767
secrets: inherit

benchmark/CMakeLists.txt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
cmake_minimum_required(VERSION 3.25)
1616

17-
project(benchmark-error-handling LANGUAGES CXX)
17+
project(benchmark_error_handling LANGUAGES CXX)
1818

1919
# Always check that the $ENV{LIBHAL_PLATFORM_LIBRARY} & $ENV{LIBHAL_PLATFORM}
2020
# environment variables are set by the profile.
@@ -31,10 +31,6 @@ endif()
3131
find_package(libhal-$ENV{LIBHAL_PLATFORM_LIBRARY} REQUIRED)
3232
find_package(prebuilt-picolibc QUIET)
3333

34-
if(${CMAKE_CROSSCOMPILING})
35-
find_package(${PACKAGE} REQUIRED)
36-
endif()
37-
3834
set(startup_source_files main.cpp filler.cpp)
3935

4036
# Makes the platform/<platform_name>.cpp file optional
@@ -73,6 +69,7 @@ foreach(test_path ${GENERATED_TEST})
7369
message(STATUS "Generating Demo for \"${elf}\"")
7470
add_executable(${elf} ${test_path})
7571

72+
target_include_directories(${elf} PRIVATE .)
7673
target_compile_options(${elf} PRIVATE
7774
-g
7875
-Werror

benchmark/conanfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ def requirements(self):
2323
bootstrap = self.python_requires["libhal-bootstrap"]
2424
bootstrap.module.add_demo_requirements(self)
2525
if self.options.platform != "mac":
26-
self.requires("libhal-exceptions/[1.2.0 || latest]")
26+
self.requires("libhal-exceptions/1.2.0")

benchmark/filler.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
// Copyright 2024 - 2025 Khalil Estell and the libhal contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
115
/**
216
* @file filler.cpp
317
*
@@ -10,8 +24,9 @@
1024
*
1125
*/
1226

13-
/**
14-
* @brief Performs some set of actions that forces the compiler to link in all
15-
* of the filler functions.
16-
*/
17-
void activate_filler();
27+
#include <platform.hpp>
28+
29+
void link_filler_functions()
30+
{
31+
// TODO(79): Fill in file with linker information
32+
}
Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ def generate_exception_file(destructor_percent: int, depth: int) -> str:
2727
#include <cstdint>
2828
#include <string_view>
2929
30-
// External functions
31-
extern void start();
32-
extern void end();
33-
extern void log_start(std::string_view);
30+
#include <platform.hpp>
3431
3532
// Global side effect to prevent optimization
3633
std::int32_t volatile side_effect = 0;
@@ -84,10 +81,24 @@ class destructor_object {{
8481

8582
# Generate function implementations
8683
for i in range(depth, 0, -1):
87-
# Determine if this function should have a destructor
88-
has_destructor = i <= destructor_count
89-
obj_type = "destructor_object" if has_destructor else "simple_object"
84+
# Calculate which functions should have destructors - evenly distributed
85+
function_index = depth - i # 0-based index for this function
86+
87+
# Calculate total destructor count and distribute evenly
88+
destructor_count = int((destructor_percent / 100.0) * depth)
89+
90+
if destructor_count == 0:
91+
has_destructor = False
92+
elif destructor_count >= depth:
93+
has_destructor = True
94+
else:
95+
# Even distribution using integer arithmetic
96+
current_position = function_index * destructor_count // depth
97+
next_position = (function_index + 1) * destructor_count // depth
98+
has_destructor = next_position > current_position
9099

100+
obj_type = "destructor_object" if has_destructor else "simple_object"
101+
obj_type = "destructor_object" if has_destructor else "simple_object"
91102
content += f'''[[gnu::noinline]]
92103
int depth_{i:02d}() {{
93104
{obj_type} obj(side_effect >> 8);
@@ -133,11 +144,38 @@ class destructor_object {{
133144
side_effect = 1; // Ensure we will throw
134145
135146
try {{
136-
depth_{depth:02d}();
137-
}} catch (const test_error& e) {{
147+
depth_70();
148+
}} catch (test_error const& e) {{
149+
end();
150+
}}
151+
152+
pause();
153+
154+
try {{
155+
depth_50();
156+
}} catch (test_error const& e) {{
157+
end();
158+
}}
159+
160+
pause();
161+
162+
try {{
163+
depth_30();
164+
}} catch (test_error const& e) {{
138165
end();
139166
}}
167+
168+
pause();
169+
170+
try {{
171+
depth_10();
172+
}} catch (test_error const& e) {{
173+
end();
174+
}}
175+
176+
pause();
140177
}}
178+
141179
'''
142180

143181
return content
@@ -154,10 +192,7 @@ def generate_result_file(destructor_percent: int, depth: int) -> str:
154192
#include <expected>
155193
#include <string_view>
156194
157-
// External functions
158-
extern void start();
159-
extern void end();
160-
extern void log_start(std::string_view);
195+
#include <platform.hpp>
161196
162197
// Global side effect to prevent optimization
163198
std::int32_t volatile side_effect = 0;
@@ -261,11 +296,23 @@ class destructor_object {{
261296
# Generate test runner
262297
content += f'''// Test runner
263298
void run_test() {{
264-
log_start("RESULT_{destructor_percent}PCT_DEPTH{depth}");
299+
log_start("RESULT-{destructor_percent}%-DEPTH{depth}");
265300
side_effect = 1; // Ensure we will return error
266301
267-
auto result = depth_{depth:02d}();
268-
if (!result) {{
302+
auto result_70 = depth_70();
303+
if (!result_70) {{
304+
end();
305+
}}
306+
auto result_50 = depth_50();
307+
if (!result_50) {{
308+
end();
309+
}}
310+
auto result_30 = depth_30();
311+
if (!result_30) {{
312+
end();
313+
}}
314+
auto result_10 = depth_10();
315+
if (!result_10) {{
269316
end();
270317
}}
271318
}}
@@ -303,15 +350,14 @@ def main():
303350
"""Generate test files for all combinations."""
304351

305352
destructor_percentages = [0, 25, 50, 75, 100]
306-
depths = [10, 30, 50, 70]
353+
max_depth = 70
307354
output_dir = Path("generated_tests")
308355

309356
for destructor_pct in destructor_percentages:
310-
for depth in depths:
311-
generate_test_files(destructor_pct, depth, output_dir)
357+
generate_test_files(destructor_pct, max_depth, output_dir)
312358

313359
print(
314-
f"\nGenerated {len(destructor_percentages) * len(depths) * 2} test files in {output_dir}/")
360+
f"\nGenerated {len(destructor_percentages) * 2} test files in {output_dir}/")
315361

316362

317363
if __name__ == "__main__":

0 commit comments

Comments
 (0)