Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,55 @@ jobs:
with:
run: bazel run //examples/google_benchmark_bazel:my_benchmark --//core:codspeed_mode=${{ matrix.codspeed-mode }}
token: ${{ secrets.CODSPEED_TOKEN }}

windows-cmake-build:
strategy:
matrix:
codspeed-mode: ["off", "walltime"]
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Cache build
uses: actions/cache@v3
with:
path: examples/google_benchmark_cmake/build
key: ${{ runner.os }}-build-${{ matrix.codspeed-mode }}-${{ hashFiles('**/CMakeLists.txt') }}

- name: Create build directory
run: |
if (-not (Test-Path examples\google_benchmark_cmake\build)) {
mkdir examples\google_benchmark_cmake\build
}
shell: pwsh

- name: Build benchmark example
run: |
cd examples\google_benchmark_cmake\build
cmake -DCODSPEED_MODE=${{ matrix.codspeed-mode }} ..
cmake --build . --config Release
shell: pwsh

windows-bazel-build:
strategy:
matrix:
codspeed-mode: ["off", "walltime"]
runs-on: windows-latest
steps:
- uses: actions/checkout@v4

- name: Set up Bazel
uses: bazel-contrib/[email protected]
with:
# Avoid downloading Bazel every time.
bazelisk-cache: true
# Store build cache per workflow.
disk-cache: ${{ github.workflow }}
# Share repository cache between workflows.
repository-cache: true

- name: Build benchmark example
run: |
bazel build //examples/google_benchmark_bazel:my_benchmark --//core:codspeed_mode=${{ matrix.codspeed-mode }}
shell: pwsh
11 changes: 10 additions & 1 deletion core/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,21 @@ load("@rules_cc//cc:defs.bzl", "cc_library")

CODSPEED_VERSION = "1.1.1"

config_setting(
name = "windows",
constraint_values = ["@platforms//os:windows"],
)

# Define the codspeed library
cc_library(
name = "codspeed",
srcs = glob(["src/**/*.cpp"]),
srcs = glob(["src/**/*.cpp"] + ["src/**/*.h"]),
hdrs = glob(["include/**/*.h"] + ["include/**/*.hpp"]),
includes = ["include"],
copts = select({
":windows": ["/std:c++17"],
"//conditions:default": [],
}),
defines = [
"CODSPEED_VERSION=\\\"{}\\\"".format(CODSPEED_VERSION),
] + select({
Expand Down
6 changes: 3 additions & 3 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ set_property(
)

if(NOT CODSPEED_MODE STREQUAL "off")
target_compile_definitions(codspeed INTERFACE -DCODSPEED_ENABLED)
target_compile_definitions(codspeed PUBLIC -DCODSPEED_ENABLED)

if(NOT CMAKE_BUILD_TYPE)
message(
Expand All @@ -95,10 +95,10 @@ if(NOT CODSPEED_MODE STREQUAL "off")
if(CODSPEED_MODE STREQUAL "instrumentation")
target_compile_definitions(
codspeed
INTERFACE -DCODSPEED_INSTRUMENTATION
PUBLIC -DCODSPEED_INSTRUMENTATION
)
elseif(CODSPEED_MODE STREQUAL "walltime")
target_compile_definitions(codspeed INTERFACE -DCODSPEED_WALLTIME)
target_compile_definitions(codspeed PUBLIC -DCODSPEED_WALLTIME)
else()
message(
FATAL_ERROR
Expand Down
3 changes: 2 additions & 1 deletion core/include/codspeed.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef CODSPEED_H
#define CODSPEED_H

#include <cstdint>
#include <string>
#include <vector>

Expand Down Expand Up @@ -33,7 +34,7 @@ class CodSpeed {
struct RawWalltimeBenchmark {
std::string name;
std::string uri;
long iter_per_round;
uint64_t iter_per_round;
double mean_ns;
double median_ns;
double stdev_ns;
Expand Down
10 changes: 10 additions & 0 deletions core/include/measurement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

#include <string>

#ifdef CODSPEED_INSTRUMENTATION
#include "callgrind.h"
#endif

inline std::string get_version() {
#ifdef CODSPEED_VERSION
Expand All @@ -13,6 +15,7 @@ inline std::string get_version() {
#endif
}

#ifdef CODSPEED_INSTRUMENTATION
inline bool measurement_is_instrumented() { return RUNNING_ON_VALGRIND; }

inline void measurement_set_metadata() {
Expand All @@ -30,5 +33,12 @@ __attribute__((always_inline)) inline void measurement_stop(
CALLGRIND_STOP_INSTRUMENTATION;
CALLGRIND_DUMP_STATS_AT(name.c_str());
};
#else
// Stub implementations for non-instrumentation builds
inline bool measurement_is_instrumented() { return false; }
inline void measurement_set_metadata() {}
inline void measurement_start() {}
inline void measurement_stop(const std::string &name) { (void)name; }
#endif

#endif // MEASUREMENT_H
2 changes: 1 addition & 1 deletion core/src/codspeed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void CodSpeed::start_benchmark(const std::string &name) {

// Sanity check URI and add a placeholder if format is wrong
if (name.find("::") == std::string::npos) {
std::string uri = "unknown_file::" + name;
uri = "unknown_file::" + name;
std::cout << "WARNING: Benchmark name does not contain '::'. Using URI: "
<< uri << std::endl;
}
Expand Down
4 changes: 4 additions & 0 deletions core/src/uri.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ std::string extract_lambda_namespace(const std::string &pretty_func) {
return extract_namespace_clang(pretty_func);
#elif __GNUC__
return extract_namespace_gcc(pretty_func);
#elif _MSC_VER
// MSVC doesn't support __PRETTY_FUNCTION__ in the same way
// Return empty string as fallback for Windows
return {};
#else
#error "Unsupported compiler"
#endif
Expand Down
13 changes: 13 additions & 0 deletions core/src/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef CODSPEED_UTILS_H
#define CODSPEED_UTILS_H

#include <string>

namespace codspeed {

// Cross-platform getenv wrapper
std::string safe_getenv(const char* var_name);

} // namespace codspeed

#endif // CODSPEED_UTILS_H
9 changes: 5 additions & 4 deletions core/src/walltime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <string>

#include "codspeed.h"
#include "utils.h"
#ifdef _WIN32
#include <process.h>
#else
Expand All @@ -31,7 +32,7 @@ struct BenchmarkStats {
double total_time;
uint64_t iqr_outlier_rounds;
uint64_t stdev_outlier_rounds;
long iter_per_round;
uint64_t iter_per_round;
uint64_t warmup_iters;
};

Expand Down Expand Up @@ -108,7 +109,7 @@ void write_codspeed_benchmarks_to_json(
std::string creator_name = "codspeed-cpp";
std::string creator_version = CODSPEED_VERSION;
#ifdef _WIN32
pid_t creator_pid = _getpid();
auto creator_pid = _getpid();
#else
pid_t creator_pid = getpid();
#endif
Expand Down Expand Up @@ -169,8 +170,8 @@ void write_codspeed_benchmarks_to_json(
oss << "}";

// Determine the directory path
const char *profile_folder = std::getenv("CODSPEED_PROFILE_FOLDER");
std::string directory = profile_folder ? profile_folder : ".";
std::string profile_folder = safe_getenv("CODSPEED_PROFILE_FOLDER");
std::string directory = profile_folder.empty() ? "." : profile_folder;

// Create the results directory if it does not exist
std::filesystem::path results_path = directory + "/results";
Expand Down
23 changes: 21 additions & 2 deletions core/src/workspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,32 @@
#include <filesystem>

#include "codspeed.h"
#include "utils.h"

namespace codspeed {

std::string get_path_relative_to_workspace(const std::string &path) {
std::string safe_getenv(const char* var_name) {
#ifdef _WIN32
// On Windows, use _dupenv_s instead of std::getenv for thread safety
char* value;
size_t len;
errno_t err = _dupenv_s(&value, &len, var_name);
if (err == 0 && value) {
std::string result(value);
free(value);
return result;
}
return "";
#else
const char* value = std::getenv(var_name);
return value ? value : "";
#endif
}

std::string get_path_relative_to_workspace(const std::string& path) {
// 1. Check for bazel usage, through the BUILD_WORKSPACE_DIRECTORY env var
// If so, __FILE__ will already be relative to the bazel workspace root
if (std::getenv("BUILD_WORKSPACE_DIRECTORY") != NULL) {
if (!safe_getenv("BUILD_WORKSPACE_DIRECTORY").empty()) {
return path;
}

Expand Down
7 changes: 7 additions & 0 deletions core/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,12 @@ target_link_libraries(unit_tests
GTest::gtest_main
)

# Treat warnings as errors for tests to catch issues early
if(MSVC)
target_compile_options(unit_tests PRIVATE /W4 /WX)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(unit_tests PRIVATE -Wall -Wextra -Werror)
endif()

include(GoogleTest)
gtest_discover_tests(unit_tests)
10 changes: 9 additions & 1 deletion examples/google_benchmark_bazel/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
config_setting(
name = "windows",
constraint_values = ["@platforms//os:windows"],
)

cc_binary(
name = "my_benchmark",
srcs = glob(["*.cpp", "*.hpp"]),
copts = ["-Wall", "-Wextra", "-Werror"],
copts = select({
":windows": ["/std:c++17", "/W4", "/WX"],
"//conditions:default": ["-Wall", "-Wextra", "-Werror"],
}),
deps = [
"//google_benchmark:benchmark",
],
Expand Down
21 changes: 19 additions & 2 deletions examples/google_benchmark_cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
cmake_minimum_required(VERSION 3.12)
include(FetchContent)

project(codspeed_picobench_compat VERSION 0.0.0 LANGUAGES CXX)
project(codspeed_google_benchmark_example VERSION 0.0.0 LANGUAGES CXX)

# Treat warnings as errors
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_compile_options(-Wall -Wextra -Werror)
elseif(MSVC)
# Set C++17 standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_compile_options(
/W4
/WX
/wd5051 # Ignore [[maybe_unused]] C++17 warnings from Google Benchmark
/wd4038 # Ignore STL <filesystem> C++17 warnings
)
endif()

# On the small benchmarks of this repo, most of the benches will be optimized out, but this is expected.
set(CMAKE_BUILD_TYPE RelWithDebInfo)

option(BENCHMARK_ENABLE_GTEST_TESTS OFF)
# Disable Google Benchmark tests for examples
set(BENCHMARK_ENABLE_GTEST_TESTS
OFF
CACHE BOOL
"Enable testing of the benchmark library."
FORCE
)

FetchContent_Declare(
google_benchmark
Expand Down
Loading
Loading