Skip to content

Commit 3e2d001

Browse files
feat: only run benchmark once in instrumentation mode
This also adds support for codspeed mode definition at build time
1 parent 6045844 commit 3e2d001

File tree

7 files changed

+137
-73
lines changed

7 files changed

+137
-73
lines changed

google_benchmark/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ option(BENCHMARK_ENABLE_ASSEMBLY_TESTS "Enable building and running the assembly
9797
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
9898
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
9999

100+
# Codspeed specific configuration
101+
include(Codspeed)
100102

101103
# Read the git tags to determine the project version
102104
include(GetGitVersion)

google_benchmark/cmake/Codspeed.cmake

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Step 1: Check if CODSPEED_MODE is set via the command line
2+
3+
# CMake cache kind of breaks this mechanism, keeping it for first time
4+
# defaulting
5+
if(NOT DEFINED CODSPEED_MODE)
6+
# Step 2: Check the environment variable CODSPEED_MODE
7+
if(DEFINED $ENV{CODSPEED_RUNNER_MODE})
8+
set(CODSPEED_MODE $ENV{CODSPEED_RUNNER_MODE} FORCE)
9+
else()
10+
# Step 3: Default to "instrumentation" if no value is provided
11+
set(CODSPEED_MODE "instrumentation")
12+
endif()
13+
endif()
14+
15+
# Define a preprocessor macro based on the build mode
16+
if(CODSPEED_MODE STREQUAL "instrumentation")
17+
target_compile_definitions(codspeed INTERFACE -DCODSPEED_INSTRUMENTATION)
18+
elseif(CODSPEED_MODE STREQUAL "walltime")
19+
target_compile_definitions(codspeed INTERFACE -DCODSPEED_WALLTIME)
20+
else()
21+
message(
22+
FATAL_ERROR
23+
"Invalid build mode: ${CODSPEED_MODE}. Use 'instrumentation' or 'walltime'."
24+
)
25+
endif()
26+
27+
message(STATUS "Build mode set to: ${CODSPEED_MODE}")

google_benchmark/src/CMakeLists.txt

Lines changed: 57 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,36 @@
1-
#Allow the source files to find headers in src /
1+
# Allow the source files to find headers in src /
22
include(GNUInstallDirs)
33
include_directories(${PROJECT_SOURCE_DIR}/src)
44

5-
if (DEFINED BENCHMARK_CXX_LINKER_FLAGS)
5+
if(DEFINED BENCHMARK_CXX_LINKER_FLAGS)
66
list(APPEND CMAKE_SHARED_LINKER_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
77
list(APPEND CMAKE_MODULE_LINKER_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
88
endif()
99

10-
file(GLOB
11-
SOURCE_FILES
12-
*.cc
13-
${PROJECT_SOURCE_DIR}/include/benchmark/*.h
14-
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
10+
file(GLOB SOURCE_FILES *.cc ${PROJECT_SOURCE_DIR}/include/benchmark/*.h
11+
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
1512
file(GLOB BENCHMARK_MAIN "benchmark_main.cc")
1613
foreach(item ${BENCHMARK_MAIN})
1714
list(REMOVE_ITEM SOURCE_FILES "${item}")
1815
endforeach()
1916

2017
add_library(benchmark ${SOURCE_FILES})
2118
add_library(benchmark::benchmark ALIAS benchmark)
22-
set_target_properties(benchmark PROPERTIES
23-
OUTPUT_NAME "benchmark"
24-
VERSION ${GENERIC_LIB_VERSION}
25-
SOVERSION ${GENERIC_LIB_SOVERSION}
26-
)
27-
target_include_directories(benchmark PUBLIC
28-
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
29-
)
19+
set_target_properties(
20+
benchmark
21+
PROPERTIES OUTPUT_NAME "benchmark"
22+
VERSION ${GENERIC_LIB_VERSION}
23+
SOVERSION ${GENERIC_LIB_SOVERSION})
24+
target_include_directories(
25+
benchmark PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
3026

3127
set_property(
3228
SOURCE benchmark.cc
3329
APPEND
34-
PROPERTY COMPILE_DEFINITIONS
35-
BENCHMARK_VERSION="${VERSION}"
36-
)
30+
PROPERTY COMPILE_DEFINITIONS BENCHMARK_VERSION="${VERSION}")
3731

3832
# libpfm, if available
39-
if (PFM_FOUND)
33+
if(PFM_FOUND)
4034
target_link_libraries(benchmark PRIVATE PFM::libpfm)
4135
target_compile_definitions(benchmark PRIVATE -DHAVE_LIBPFM)
4236
endif()
@@ -55,7 +49,6 @@ if(HAVE_LIB_RT)
5549
target_link_libraries(benchmark PRIVATE rt)
5650
endif(HAVE_LIB_RT)
5751

58-
5952
# We need extra libraries on Windows
6053
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
6154
target_link_libraries(benchmark PRIVATE shlwapi)
@@ -67,24 +60,23 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
6760
set(BENCHMARK_PRIVATE_LINK_LIBRARIES -lkstat)
6861
endif()
6962

70-
if (NOT BUILD_SHARED_LIBS)
63+
if(NOT BUILD_SHARED_LIBS)
7164
target_compile_definitions(benchmark PUBLIC -DBENCHMARK_STATIC_DEFINE)
7265
endif()
7366

7467
# Benchmark main library
7568
add_library(benchmark_main "benchmark_main.cc")
7669
add_library(benchmark::benchmark_main ALIAS benchmark_main)
77-
set_target_properties(benchmark_main PROPERTIES
78-
OUTPUT_NAME "benchmark_main"
79-
VERSION ${GENERIC_LIB_VERSION}
80-
SOVERSION ${GENERIC_LIB_SOVERSION}
81-
DEFINE_SYMBOL benchmark_EXPORTS
82-
)
70+
set_target_properties(
71+
benchmark_main
72+
PROPERTIES OUTPUT_NAME "benchmark_main"
73+
VERSION ${GENERIC_LIB_VERSION}
74+
SOVERSION ${GENERIC_LIB_SOVERSION}
75+
DEFINE_SYMBOL benchmark_EXPORTS)
8376
target_link_libraries(benchmark_main PUBLIC benchmark::benchmark)
8477

85-
add_subdirectory(${PROJECT_SOURCE_DIR}/../core codspeed)
86-
87-
target_link_libraries(benchmark PRIVATE codspeed)
78+
# TODO: Find a way to not expose codspeed headers to downstream users
79+
target_link_libraries(benchmark PUBLIC codspeed)
8880

8981
set(generated_dir "${PROJECT_BINARY_DIR}")
9082

@@ -100,57 +92,57 @@ set(namespace "${PROJECT_NAME}::")
10092

10193
include(CMakePackageConfigHelpers)
10294

103-
configure_package_config_file (
104-
${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in
105-
${project_config}
95+
configure_package_config_file(
96+
${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in ${project_config}
10697
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
107-
NO_SET_AND_CHECK_MACRO
108-
NO_CHECK_REQUIRED_COMPONENTS_MACRO
109-
)
98+
NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO)
11099
write_basic_package_version_file(
111-
"${version_config}" VERSION ${GENERIC_LIB_VERSION} COMPATIBILITY SameMajorVersion
112-
)
100+
"${version_config}"
101+
VERSION ${GENERIC_LIB_VERSION}
102+
COMPATIBILITY SameMajorVersion)
113103

114-
configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark.pc.in" "${pkg_config}" @ONLY)
115-
configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark_main.pc.in" "${pkg_config_main}" @ONLY)
104+
configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark.pc.in" "${pkg_config}"
105+
@ONLY)
106+
configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark_main.pc.in"
107+
"${pkg_config_main}" @ONLY)
116108

117-
export (
109+
export(
118110
TARGETS ${targets_to_export}
119111
NAMESPACE "${namespace}"
120-
FILE ${generated_dir}/${targets_export_name}.cmake
121-
)
112+
FILE ${generated_dir}/${targets_export_name}.cmake)
122113

123-
if (BENCHMARK_ENABLE_INSTALL)
124-
# Install target (will install the library to specified CMAKE_INSTALL_PREFIX variable)
114+
if(BENCHMARK_ENABLE_INSTALL)
115+
# Install target (will install the library to specified CMAKE_INSTALL_PREFIX
116+
# variable)
125117
install(
126118
TARGETS ${targets_to_export}
127119
EXPORT ${targets_export_name}
128120
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
129121
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
130122
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
131-
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
123+
INCLUDES
124+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
132125

133126
install(
134127
DIRECTORY "${PROJECT_SOURCE_DIR}/include/benchmark"
135128
"${PROJECT_BINARY_DIR}/include/benchmark"
136129
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
137-
FILES_MATCHING PATTERN "*.*h")
130+
FILES_MATCHING
131+
PATTERN "*.*h")
138132

139-
install(
140-
FILES "${project_config}" "${version_config}"
141-
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
133+
install(FILES "${project_config}" "${version_config}"
134+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
142135

143-
install(
144-
FILES "${pkg_config}" "${pkg_config_main}"
145-
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
136+
install(FILES "${pkg_config}" "${pkg_config_main}"
137+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
146138

147139
install(
148-
EXPORT "${targets_export_name}"
149-
NAMESPACE "${namespace}"
150-
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
140+
EXPORT "${targets_export_name}"
141+
NAMESPACE "${namespace}"
142+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
151143
endif()
152144

153-
if (BENCHMARK_ENABLE_DOXYGEN)
145+
if(BENCHMARK_ENABLE_DOXYGEN)
154146
find_package(Doxygen REQUIRED)
155147
set(DOXYGEN_QUIET YES)
156148
set(DOXYGEN_RECURSIVE YES)
@@ -164,22 +156,17 @@ if (BENCHMARK_ENABLE_DOXYGEN)
164156
set(DOXYGEN_BINARY_TOC YES)
165157
set(DOXYGEN_TOC_EXPAND YES)
166158
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "index.md")
167-
doxygen_add_docs(benchmark_doxygen
168-
docs
169-
include
170-
src
171-
ALL
159+
doxygen_add_docs(
160+
benchmark_doxygen docs include src ALL
172161
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
173162
COMMENT "Building documentation with Doxygen.")
174-
if (BENCHMARK_ENABLE_INSTALL AND BENCHMARK_INSTALL_DOCS)
175-
install(
176-
DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html/"
177-
DESTINATION ${CMAKE_INSTALL_DOCDIR})
163+
if(BENCHMARK_ENABLE_INSTALL AND BENCHMARK_INSTALL_DOCS)
164+
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html/"
165+
DESTINATION ${CMAKE_INSTALL_DOCDIR})
178166
endif()
179167
else()
180-
if (BENCHMARK_ENABLE_INSTALL AND BENCHMARK_INSTALL_DOCS)
181-
install(
182-
DIRECTORY "${PROJECT_SOURCE_DIR}/docs/"
183-
DESTINATION ${CMAKE_INSTALL_DOCDIR})
168+
if(BENCHMARK_ENABLE_INSTALL AND BENCHMARK_INSTALL_DOCS)
169+
install(DIRECTORY "${PROJECT_SOURCE_DIR}/docs/"
170+
DESTINATION ${CMAKE_INSTALL_DOCDIR})
184171
endif()
185172
endif()

google_benchmark/src/benchmark.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,13 @@ void RunBenchmarks(const std::vector<BenchmarkInstance>& benchmarks,
382382
// Note the file_reporter can be null.
383383
BM_CHECK(display_reporter != nullptr);
384384

385-
hello_codspeed();
386-
387385
// Determine the width of the name field using a minimum width of 10.
386+
#ifdef CODSPEED_INSTRUMENTATION
387+
std::cout << "Codspeed mode: instrumentation" << "\n";
388+
#elif defined(CODSPEED_WALLTIME)
389+
std::cout << "Codspeed mode walltime" << "\n";
390+
#endif
391+
388392
bool might_have_aggregates = FLAGS_benchmark_repetitions > 1;
389393
size_t name_field_width = 10;
390394
size_t stat_field_width = 0;

google_benchmark/src/benchmark_api_internal.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <cinttypes>
44

5+
#include "codspeed.h"
56
#include "string_util.h"
67

78
namespace benchmark {
@@ -89,6 +90,21 @@ BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx,
8990
teardown_ = benchmark_.teardown_;
9091
}
9192

93+
#ifdef CODSPEED_INSTRUMENTATION
94+
State BenchmarkInstance::RunInstrumented(
95+
CodSpeed* codspeed, internal::ThreadTimer* timer,
96+
internal::ThreadManager* manager,
97+
internal::PerfCountersMeasurement* perf_counters_measurement,
98+
ProfilerManager* profiler_manager) const {
99+
State st(name_.function_name, 1, args_, 0, 1, timer, manager,
100+
perf_counters_measurement, profiler_manager);
101+
codspeed->start_benchmark(name().str());
102+
benchmark_.Run(st);
103+
codspeed->end_benchmark();
104+
return st;
105+
}
106+
#endif
107+
92108
State BenchmarkInstance::Run(
93109
IterationCount iters, int thread_id, internal::ThreadTimer* timer,
94110
internal::ThreadManager* manager,

google_benchmark/src/benchmark_api_internal.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#include <vector>
1010

1111
#include "benchmark/benchmark.h"
12+
#ifdef CODSPEED_INSTRUMENTATION
13+
#include "codspeed.h"
14+
#endif
1215
#include "commandlineflags.h"
1316

1417
namespace benchmark {
@@ -34,7 +37,13 @@ class BenchmarkInstance {
3437
BigO complexity() const { return complexity_; }
3538
BigOFunc* complexity_lambda() const { return complexity_lambda_; }
3639
const std::vector<Statistics>& statistics() const { return statistics_; }
37-
int repetitions() const { return repetitions_; }
40+
int repetitions() const {
41+
#ifdef CODSPEED_INSTRUMENTATION
42+
return 1;
43+
#else
44+
return repetitions_;
45+
#endif
46+
}
3847
double min_time() const { return min_time_; }
3948
double min_warmup_time() const { return min_warmup_time_; }
4049
IterationCount iterations() const { return iterations_; }
@@ -47,6 +56,14 @@ class BenchmarkInstance {
4756
internal::PerfCountersMeasurement* perf_counters_measurement,
4857
ProfilerManager* profiler_manager) const;
4958

59+
#ifdef CODSPEED_INSTRUMENTATION
60+
State RunInstrumented(
61+
CodSpeed* codspeed, internal::ThreadTimer* timer,
62+
internal::ThreadManager* manager,
63+
internal::PerfCountersMeasurement* perf_counters_measurement,
64+
ProfilerManager* profiler_manager) const;
65+
#endif
66+
5067
private:
5168
BenchmarkName name_;
5269
Benchmark& benchmark_;

google_benchmark/src/benchmark_runner.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <utility>
4343

4444
#include "check.h"
45+
#include "codspeed.h"
4546
#include "colorprint.h"
4647
#include "commandlineflags.h"
4748
#include "complexity.h"
@@ -464,6 +465,16 @@ void BenchmarkRunner::DoOneRepetition() {
464465

465466
const bool is_the_first_repetition = num_repetitions_done == 0;
466467

468+
#ifdef CODSPEED_INSTRUMENTATION
469+
std::unique_ptr<internal::ThreadManager> manager;
470+
manager.reset(new internal::ThreadManager(b.threads()));
471+
internal::ThreadTimer timer = internal::ThreadTimer::Create();
472+
State st = b.RunInstrumented(CodSpeed::getInstance(), &timer, manager.get(),
473+
nullptr, nullptr);
474+
475+
return;
476+
#endif
477+
467478
// In case a warmup phase is requested by the benchmark, run it now.
468479
// After running the warmup phase the BenchmarkRunner should be in a state as
469480
// this warmup never happened except the fact that warmup_done is set. Every

0 commit comments

Comments
 (0)