Skip to content

Commit 2cbdbb5

Browse files
ConorWilliamsConor
authored andcommitted
[V4] Benchmark skeleton (#48)
* mv license * same checkout version * move to frame * casting checks * cmake for benchmark * fib * add benchmark dep * new benchmark structure * pragma once on headers * version test * better version test * add src * strip prefix * bench preset * benchmark as a test * add benchmark test to preset * move to todo * use variables * drop no plt * rename * proper fib benchmark * drop todo * spell * macros * no-except safe * even better errors * exception safe * Resolve review comments: add include guard, fix macro evaluations, improve error messages Co-authored-by: ConorWilliams <47435400+ConorWilliams@users.noreply.github.com> * Complete review comment resolution Co-authored-by: ConorWilliams <47435400+ConorWilliams@users.noreply.github.com> * Add CodeQL symlink to .gitignore Co-authored-by: ConorWilliams <47435400+ConorWilliams@users.noreply.github.com> * Update .gitignore * Add Fibonacci serial benchmark with direct return Co-authored-by: ConorWilliams <47435400+ConorWilliams@users.noreply.github.com> * Complete: Add Fibonacci serial benchmark with direct return Co-authored-by: ConorWilliams <47435400+ConorWilliams@users.noreply.github.com> * Remove CodeQL artifact and update gitignore Co-authored-by: ConorWilliams <47435400+ConorWilliams@users.noreply.github.com> * Fix .gitignore formatting Co-authored-by: ConorWilliams <47435400+ConorWilliams@users.noreply.github.com> * Remove doxygen-specific bits from macros.hpp Co-authored-by: ConorWilliams <47435400+ConorWilliams@users.noreply.github.com> * Complete removal of doxygen-specific bits Co-authored-by: ConorWilliams <47435400+ConorWilliams@users.noreply.github.com> * undo _codeql shenanigens * reoder bench naming convention * shorten * macros * prevent loop invariant lifting * spell * use do-not opt for basic fib as well
1 parent 79bd6b3 commit 2cbdbb5

17 files changed

Lines changed: 403 additions & 70 deletions

File tree

.github/workflows/linear.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: Checkout
13-
uses: actions/checkout@v4
13+
uses: actions/checkout@v6
1414
with:
1515
ref: ${{ github.event.pull_request.head.sha || github.sha }}
1616
fetch-depth: 0
@@ -30,4 +30,5 @@ jobs:
3030
exit 1
3131
else
3232
echo "No merge commits detected. Linear history check passed."
33-
fi
33+
fi
34+

.github/workflows/linux.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
uses: Homebrew/actions/setup-homebrew@master
2323

2424
- name: Install Dependencies
25-
run: brew install cmake ninja gcc binutils catch2
25+
run: brew install cmake ninja gcc binutils catch2 google-benchmark
2626

2727
- name: Configure
2828
run: cmake --preset ${{ matrix.preset }} -DCMAKE_TOOLCHAIN_FILE=cmake/gcc-brew-toolchain.cmake
@@ -32,4 +32,3 @@ jobs:
3232

3333
- name: Test
3434
run: ctest --preset ${{ matrix.preset }}
35-

.github/workflows/macos.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
uses: Homebrew/actions/setup-homebrew@master
2323

2424
- name: Install Dependencies
25-
run: brew install cmake ninja llvm catch2
25+
run: brew install cmake ninja llvm catch2 google-benchmark
2626

2727
- name: Configure
2828
run: cmake --preset ${{ matrix.preset }} -DCMAKE_TOOLCHAIN_FILE=cmake/llvm-brew-toolchain.cmake

.legacy/include/libfork/core/macro.hpp

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -192,28 +192,6 @@ using std::unreachable;
192192
#define LF_ASSERT(expr) LF_ASSUME(expr)
193193
#endif
194194

195-
/**
196-
* @brief Macro to prevent a function to be inlined.
197-
*/
198-
#if !defined(LF_NOINLINE)
199-
#if defined(_MSC_VER) && !defined(__clang__)
200-
#define LF_NOINLINE __declspec(noinline)
201-
#elif defined(__GNUC__) && __GNUC__ > 3
202-
// Clang also defines __GNUC__ (as 4)
203-
#if defined(__CUDACC__)
204-
// nvcc doesn't always parse __noinline__, see: https://svn.boost.org/trac/boost/ticket/9392
205-
#define LF_NOINLINE __attribute__((noinline))
206-
#elif defined(__HIP__)
207-
// See https://github.com/boostorg/config/issues/392
208-
#define LF_NOINLINE __attribute__((noinline))
209-
#else
210-
#define LF_NOINLINE __attribute__((__noinline__))
211-
#endif
212-
#else
213-
#define LF_NOINLINE
214-
#endif
215-
#endif
216-
217195
/**
218196
* @brief Force no-inline for clang, works-around https://github.com/llvm/llvm-project/issues/63022.
219197
*
@@ -229,28 +207,6 @@ using std::unreachable;
229207
#define LF_CLANG_TLS_NOINLINE
230208
#endif
231209

232-
/**
233-
* @brief Macro to use next to 'inline' to force a function to be inlined.
234-
*
235-
* \rst
236-
*
237-
* .. note::
238-
*
239-
* This does not imply the c++'s `inline` keyword which also has an effect on linkage.
240-
*
241-
* \endrst
242-
*/
243-
#if !defined(LF_FORCEINLINE)
244-
#if defined(_MSC_VER) && !defined(__clang__)
245-
#define LF_FORCEINLINE __forceinline
246-
#elif defined(__GNUC__) && __GNUC__ > 3
247-
// Clang also defines __GNUC__ (as 4)
248-
#define LF_FORCEINLINE __attribute__((__always_inline__))
249-
#else
250-
#define LF_FORCEINLINE
251-
#endif
252-
#endif
253-
254210
#if defined(__clang__) && defined(__has_attribute)
255211
/**
256212
* @brief Compiler specific attribute.

CMakeLists.txt

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,24 @@ read_version(${CMAKE_CURRENT_SOURCE_DIR}/include/libfork/version.hpp)
1010
project(
1111
libfork
1212
VERSION ${version_major}.${version_minor}.${version_patch}
13-
DESCRIPTION "A bleeding-edge, lock-free, wait-free, continuation-stealing fork-join library built on C++20's coroutines."
1413
LANGUAGES CXX
1514
)
1615

17-
# Tell CMake that we explicitly want `import std`. This will initialize the
18-
# property on all targets declared after this to 1
19-
# TODO: set property per target
20-
set(CMAKE_CXX_MODULE_STD 1)
16+
# ---- Project options ----
17+
18+
option(libfork_DEV_MODE "Enable developer build (tests/benchmarks/etc) for libfork" OFF)
2119

2220
# ---- System dependencies ----
2321

2422
find_package(Threads REQUIRED)
2523

2624
# ===========================
2725

26+
# Tell CMake that we explicitly want `import std`. This will initialize the
27+
# property on all targets declared after this to 1
28+
# TODO: set property per target
29+
set(CMAKE_CXX_MODULE_STD 1)
30+
2831
add_library(libfork_libfork)
2932
add_library(libfork::libfork ALIAS libfork_libfork)
3033

@@ -39,6 +42,7 @@ target_sources(libfork_libfork
3942
PUBLIC
4043
FILE_SET HEADERS FILES
4144
include/libfork/version.hpp
45+
include/libfork/macros.hpp
4246
BASE_DIRS
4347
include
4448
)
@@ -56,16 +60,17 @@ target_sources(libfork_libfork
5660

5761
# ======================
5862

59-
# TODO: gate below this point behind a dev mode
63+
if(libfork_DEV_MODE)
6064

61-
include(CTest) # Enables the BUILD_TESTING option
62-
63-
if(BUILD_TESTING)
64-
add_subdirectory(test)
65-
endif()
65+
include(CTest) # Enables the BUILD_TESTING option
6666

67+
if(BUILD_TESTING)
68+
add_subdirectory(test)
69+
endif()
6770

71+
add_subdirectory(benchmark)
6872

73+
endif()
6974

7075
# list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
7176
#

CMakePresets.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"generator": "Ninja",
2323
"binaryDir": "${sourceDir}/build/${presetName}",
2424
"cacheVariables": {
25-
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
25+
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
26+
"libfork_DEV_MODE": "ON"
2627
}
2728
},
2829
{
@@ -40,7 +41,7 @@
4041
"displayName": "Release",
4142
"cacheVariables": {
4243
"CMAKE_BUILD_TYPE": "Release",
43-
"CMAKE_CXX_FLAGS": "-O3 -DNDEBUG -flto -fno-plt -march=native"
44+
"CMAKE_CXX_FLAGS": "-O3 -DNDEBUG -flto -march=native"
4445
}
4546
},
4647
{
@@ -49,7 +50,7 @@
4950
"displayName": "Release no RTTI or exceptions",
5051
"cacheVariables": {
5152
"CMAKE_BUILD_TYPE": "Release",
52-
"CMAKE_CXX_FLAGS": "-O3 -DNDEBUG -flto -fno-plt -march=native -fno-exceptions -fno-rtti"
53+
"CMAKE_CXX_FLAGS": "-O3 -DNDEBUG -flto -march=native -fno-exceptions -fno-rtti"
5354
}
5455
},
5556
{

CMakeUserPresets.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,22 @@
66
"inherits": "ci-hardened",
77
"displayName": "Hardened development build",
88
"toolchainFile": "${sourceDir}/cmake/llvm-brew-toolchain.cmake"
9+
},
10+
{
11+
"name": "bench",
12+
"inherits": "ci-release",
13+
"displayName": "Release build for benchmarks",
14+
"toolchainFile": "${sourceDir}/cmake/llvm-brew-toolchain.cmake"
915
}
1016
],
1117
"buildPresets": [
1218
{
1319
"name": "dev",
1420
"configurePreset": "dev"
21+
},
22+
{
23+
"name": "bench",
24+
"configurePreset": "bench"
1525
}
1626
],
1727
"testPresets": [
@@ -24,6 +34,16 @@
2434
"execution": {
2535
"stopOnFailure": true
2636
}
37+
},
38+
{
39+
"name": "bench",
40+
"configurePreset": "bench",
41+
"output": {
42+
"outputOnFailure": true
43+
},
44+
"execution": {
45+
"stopOnFailure": true
46+
}
2747
}
2848
],
2949
"workflowPresets": [
@@ -44,6 +64,24 @@
4464
"name": "dev"
4565
}
4666
]
67+
},
68+
{
69+
"name": "bench",
70+
"displayName": "Release Build (including Benchmarks)",
71+
"steps": [
72+
{
73+
"type": "configure",
74+
"name": "bench"
75+
},
76+
{
77+
"type": "build",
78+
"name": "bench"
79+
},
80+
{
81+
"type": "test",
82+
"name": "bench"
83+
}
84+
]
4785
}
4886
]
4987
}
File renamed without changes.

benchmark/CMakeLists.txt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
cmake_minimum_required(VERSION 4.2.1 FATAL_ERROR)
2+
3+
project(libfork_benchmark LANGUAGES CXX)
4+
5+
if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
6+
message(WARNING "It is recommended to build benchmarks in Release mode for accurate results.")
7+
endif()
8+
9+
# ---- Benchmarks ----
10+
11+
find_package(benchmark REQUIRED)
12+
13+
add_executable(libfork_benchmark)
14+
15+
target_link_libraries(libfork_benchmark
16+
PRIVATE
17+
benchmark::benchmark_main
18+
)
19+
20+
# Headers (shared between all benchmarks)
21+
target_sources(libfork_benchmark
22+
PRIVATE
23+
FILE_SET HEADERS FILES
24+
src/libfork_benchmark/common.hpp
25+
src/libfork_benchmark/fib/fib.hpp
26+
BASE_DIRS
27+
src
28+
)
29+
30+
if(BUILD_TESTING)
31+
add_test(NAME Benchmark
32+
COMMAND
33+
libfork_benchmark --benchmark_dry_run --benchmark_filter=^test/
34+
)
35+
endif()
36+
37+
# ---- Serial ----
38+
39+
target_sources(libfork_benchmark
40+
PRIVATE
41+
src/libfork_benchmark/fib/serial.cpp
42+
src/libfork_benchmark/fib/serial_return.cpp
43+
)
44+
45+
# ---- Libfork ----
46+
47+
# target_sources(libfork_benchmark
48+
# PRIVATE
49+
# src/libfork_benchmark/fib/fib.cpp
50+
# )
51+
52+
target_link_libraries(libfork_benchmark
53+
PRIVATE
54+
libfork::libfork
55+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
3+
#include <format>
4+
#include <stdexcept>
5+
6+
#include "libfork/macros.hpp"
7+
8+
struct incorrect_result : public std::runtime_error {
9+
using std::runtime_error::runtime_error;
10+
};
11+
12+
#define CHECK_RESULT(result, expected) \
13+
do { \
14+
auto &&lf_check_result_val = (result); \
15+
auto &&lf_check_expected_val = (expected); \
16+
if (lf_check_result_val != lf_check_expected_val) { \
17+
LF_THROW(incorrect_result( \
18+
std::format("{}={} != {}={}", #expected, lf_check_expected_val, #result, lf_check_result_val))); \
19+
} \
20+
} while (0)

0 commit comments

Comments
 (0)