From 10ac4a3dd8e391e1e7609ab1403a60a7afaffe3d Mon Sep 17 00:00:00 2001 From: x Date: Thu, 13 Aug 2026 20:09:31 +0000 Subject: [PATCH 01/11] test: Add CodSpeed continuous benchmarking Report the results of the existing google/benchmark suites (evmone-bench, evmone-bench-internal and evmone-precompiles-bench) to CodSpeed. The google/benchmark library is replaced with the CodSpeed compatibility layer when the CODSPEED_MODE CMake option is set, the default build is not affected. The benchmarks are executed in the CPU simulation mode by a new GitHub Actions workflow, split into shards running in parallel. --- .github/workflows/codspeed.yml | 96 +++++++++++++++++++ README.md | 3 + test/CMakeLists.txt | 41 +++++--- test/bench/bench.cpp | 17 ++-- test/bench/helpers.hpp | 10 ++ test/bench/synthetic_benchmarks.cpp | 7 +- .../find_jumpdest_bench.cpp | 7 +- test/internal_benchmarks/lru_cache_bench.cpp | 3 +- test/internal_benchmarks/modarith_bench.cpp | 7 +- test/precompiles_bench/precompiles_bench.cpp | 3 +- test/utils/CMakeLists.txt | 1 + test/utils/bench.hpp | 15 +++ 12 files changed, 182 insertions(+), 28 deletions(-) create mode 100644 .github/workflows/codspeed.yml create mode 100644 test/utils/bench.hpp diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml new file mode 100644 index 0000000000..ccb1da39db --- /dev/null +++ b/.github/workflows/codspeed.yml @@ -0,0 +1,96 @@ +# evmone: Fast Ethereum Virtual Machine implementation +# Copyright 2025 The evmone Authors. +# SPDX-License-Identifier: Apache-2.0 + +name: CodSpeed + +on: + push: + branches: + - master + pull_request: + # `workflow_dispatch` allows CodSpeed to trigger backtest + # performance analysis in order to generate initial data. + workflow_dispatch: + +permissions: + contents: read + +env: + BUILD_DIR: build + CMAKE_BUILD_PARALLEL_LEVEL: 4 + +jobs: + build: + name: Build benchmarks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + submodules: recursive + + - name: Configure + # RelWithDebInfo keeps the optimizations on and adds the debug information + # needed by CodSpeed to attribute the measurements to the source code. + run: > + cmake -S . -B $BUILD_DIR + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DBUILD_SHARED_LIBS=OFF + -DEVMONE_TESTING=ON + -DCODSPEED_MODE=simulation + + - name: Build + run: cmake --build $BUILD_DIR --target evmone-bench evmone-bench-internal evmone-precompiles-bench + + - name: Upload benchmark executables + uses: actions/upload-artifact@v7 + with: + name: benchmarks + path: ${{ env.BUILD_DIR }}/bin/ + retention-days: 1 + + benchmark: + name: Benchmark ${{ matrix.name }} + needs: build + runs-on: ubuntu-latest + permissions: + contents: read # required for actions/checkout + id-token: write # required for OIDC authentication with CodSpeed + strategy: + fail-fast: false + # The benchmarks are split into shards executed in parallel. + # CodSpeed aggregates the results of all the shards of a single workflow run. + matrix: + include: + - name: synth + run: bin/evmone-bench --benchmark_filter=synth + - name: micro + run: bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter=micro + - name: main + run: bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter='main/(blake2b|sha1|structarray|swap_math|weierstrudel)' + - name: snailtracer + run: bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter=main/snailtracer + - name: internal + run: bin/evmone-bench-internal + - name: precompiles + run: bin/evmone-precompiles-bench + steps: + - uses: actions/checkout@v5 + with: + submodules: recursive + + - name: Download benchmark executables + uses: actions/download-artifact@v7 + with: + name: benchmarks + path: bin + + - name: Make the benchmark executables executable + # The executable permission is not preserved by the artifact upload. + run: chmod +x bin/* + + - name: Run benchmarks + uses: CodSpeedHQ/action@v5 + with: + mode: simulation + run: ${{ matrix.run }} diff --git a/README.md b/README.md index 1ae2f1eeea..1c127a110d 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![ethereum badge]][ethereum] [![readme style standard badge]][standard readme] [![codecov badge]][codecov] +[![codspeed badge]][codspeed] [![circleci badge]][circleci] [![appveyor badge]][appveyor] [![license badge]][Apache License, Version 2.0] @@ -128,6 +129,7 @@ Licensed under the [Apache License, Version 2.0]. [appveyor]: https://ci.appveyor.com/project/chfast/evmone/branch/master [circleci]: https://circleci.com/gh/ethereum/evmone/tree/master [codecov]: https://codecov.io/gh/ethereum/evmone/ +[codspeed]: https://app.codspeed.io/ipsilon/evmone?utm_source=badge [Apache License, Version 2.0]: LICENSE [ethereum]: https://ethereum.org [EVMC]: https://github.com/ethereum/evmc @@ -143,6 +145,7 @@ Licensed under the [Apache License, Version 2.0]. [appveyor badge]: https://img.shields.io/appveyor/ci/chfast/evmone/master.svg?logo=appveyor [circleci badge]: https://img.shields.io/circleci/project/github/ethereum/evmone/master.svg?logo=circleci [codecov badge]: https://img.shields.io/codecov/c/github/ethereum/evmone.svg?logo=codecov +[codspeed badge]: https://img.shields.io/endpoint?url=https://codspeed.io/badge.json [ethereum badge]: https://img.shields.io/badge/ethereum-EVM-informational.svg?logo=ethereum [license badge]: https://img.shields.io/github/license/ethereum/evmone.svg?logo=apache [readme style standard badge]: https://img.shields.io/badge/readme%20style-standard-brightgreen.svg diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7743685105..3b673e9deb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,23 +13,42 @@ find_package(CLI11 CONFIG REQUIRED) hunter_add_package(GTest) find_package(GTest CONFIG REQUIRED) -FetchContent_Declare( - benchmark - URL https://github.com/google/benchmark/archive/refs/tags/v1.9.5.tar.gz - URL_HASH SHA256=9631341c82bac4a288bef951f8b26b41f69021794184ece969f8473977eaa340 -) block() set(BUILD_SHARED_LIBS OFF) set(BENCHMARK_ENABLE_TESTING OFF) set(BENCHMARK_ENABLE_INSTALL OFF) + if(NOT CODSPEED_MODE) + FetchContent_Declare( + benchmark + URL https://github.com/google/benchmark/archive/refs/tags/v1.9.5.tar.gz + URL_HASH SHA256=9631341c82bac4a288bef951f8b26b41f69021794184ece969f8473977eaa340 + ) + else() + # Replace google/benchmark with CodSpeed's compatibility layer to report the benchmark + # results to https://codspeed.io. It provides the same benchmark::benchmark target, + # so the benchmark targets need no changes. + FetchContent_Declare( + benchmark + GIT_REPOSITORY https://github.com/CodSpeedHQ/codspeed-cpp + GIT_TAG f5a917fdd14db7293bd37acb682873fec19f8b6c # v2.4.0 + GIT_SHALLOW FALSE + SOURCE_SUBDIR google_benchmark + ) + endif() FetchContent_MakeAvailable(benchmark) endblock() -set_target_properties( - benchmark benchmark_main PROPERTIES - COMPILE_OPTIONS $<$:-w> - CXX_CLANG_TIDY "" - SYSTEM TRUE # TODO(cmake-3.26): Use the SYSTEM option of FetchContent_Declare(). -) + +foreach(TARGET IN ITEMS benchmark benchmark_main codspeed instrument_hooks) + if(TARGET ${TARGET}) + set_target_properties( + ${TARGET} PROPERTIES + COMPILE_OPTIONS "$<$:-w>;$<$:-w>" + C_CLANG_TIDY "" + CXX_CLANG_TIDY "" + SYSTEM TRUE # TODO(cmake-3.26): Use the SYSTEM option of FetchContent_Declare(). + ) + endif() +endforeach() include(CableBuildInfo) cable_add_buildinfo_library(PROJECT_NAME evmone) diff --git a/test/bench/bench.cpp b/test/bench/bench.cpp index 8c45f83693..fc757f3cc2 100644 --- a/test/bench/bench.cpp +++ b/test/bench/bench.cpp @@ -116,7 +116,7 @@ void register_benchmarks(std::span benchmark_cases) { if (advanced_vm != nullptr) { - RegisterBenchmark("advanced/analyse/" + b.name, [&b](State& state) { + RegisterBenchmark(EVMONE_BENCH_NAME("advanced/analyse/" + b.name), [&b](State& state) { bench_analyse( state, default_revision, b.code); })->Unit(kMicrosecond); @@ -124,7 +124,7 @@ void register_benchmarks(std::span benchmark_cases) if (baseline_vm != nullptr) { - RegisterBenchmark("baseline/analyse/" + b.name, [&b](State& state) { + RegisterBenchmark(EVMONE_BENCH_NAME("baseline/analyse/" + b.name), [&b](State& state) { bench_analyse( state, default_revision, b.code); })->Unit(kMicrosecond); @@ -136,7 +136,7 @@ void register_benchmarks(std::span benchmark_cases) if (advanced_vm != nullptr) { - const auto name = "advanced/execute/" + case_name; + const auto name = EVMONE_BENCH_NAME("advanced/execute/" + case_name); RegisterBenchmark(name, [&vm = *advanced_vm, &b, &input](State& state) { bench_advanced_execute(state, vm, b.code, input.input, input.expected_output); })->Unit(kMicrosecond); @@ -144,7 +144,7 @@ void register_benchmarks(std::span benchmark_cases) if (baseline_vm != nullptr) { - const auto name = "baseline/execute/" + case_name; + const auto name = EVMONE_BENCH_NAME("baseline/execute/" + case_name); RegisterBenchmark(name, [&vm = *baseline_vm, &b, &input](State& state) { bench_baseline_execute(state, vm, b.code, input.input, input.expected_output); })->Unit(kMicrosecond); @@ -152,7 +152,7 @@ void register_benchmarks(std::span benchmark_cases) if (basel_cg_vm != nullptr) { - const auto name = "bnocgoto/execute/" + case_name; + const auto name = EVMONE_BENCH_NAME("bnocgoto/execute/" + case_name); RegisterBenchmark(name, [&vm = *basel_cg_vm, &b, &input](State& state) { bench_baseline_execute(state, vm, b.code, input.input, input.expected_output); })->Unit(kMicrosecond); @@ -160,7 +160,7 @@ void register_benchmarks(std::span benchmark_cases) for (auto& [vm_name, vm] : registered_vms) { - const auto name = std::string{vm_name} + "/total/" + case_name; + const auto name = EVMONE_BENCH_NAME(std::string{vm_name} + "/total/" + case_name); RegisterBenchmark(name, [&vm, &b, &input](State& state) { bench_evmc_execute(state, vm, b.code, input.input, input.expected_output); })->Unit(kMicrosecond); @@ -234,7 +234,12 @@ std::tuple> parseargs(int argc, char** argv) int main(int argc, char** argv) { +#ifndef CODSPEED_ENABLED + // Not available in the google/benchmark version the CodSpeed compatibility + // layer is based on. Also not needed there: the measurements are done by + // CodSpeed itself. MaybeReenterWithoutASLR(argc, argv); +#endif using namespace evmone::test; try diff --git a/test/bench/helpers.hpp b/test/bench/helpers.hpp index 2f0f71a0a8..60102a9b89 100644 --- a/test/bench/helpers.hpp +++ b/test/bench/helpers.hpp @@ -12,6 +12,16 @@ #include #include +/// Decorates a dynamically registered benchmark name with the location of the registration. +/// CodSpeed identifies benchmarks by the "source_file::name" URI, which the BENCHMARK() macro +/// provides automatically, but RegisterBenchmark() does not. Without CodSpeed this is a no-op. +#ifdef CODSPEED_ENABLED +#define EVMONE_BENCH_NAME(NAME) \ + (::codspeed::get_path_relative_to_workspace(__FILE__) + "::" + (NAME)) +#else +#define EVMONE_BENCH_NAME(NAME) (NAME) +#endif + namespace evmone::test { extern std::map registered_vms; diff --git a/test/bench/synthetic_benchmarks.cpp b/test/bench/synthetic_benchmarks.cpp index 0aaa7d9243..14891744a0 100644 --- a/test/bench/synthetic_benchmarks.cpp +++ b/test/bench/synthetic_benchmarks.cpp @@ -252,9 +252,9 @@ void register_synthetic_benchmarks() for (auto& [vm_name, vm] : registered_vms) { - RegisterBenchmark(std::string{vm_name} + "/total/synth/loop_v1", + RegisterBenchmark(EVMONE_BENCH_NAME(std::string{vm_name} + "/total/synth/loop_v1"), [&vm](State& state) { bench_evmc_execute(state, vm, generate_loop_v1({})); }); - RegisterBenchmark(std::string{vm_name} + "/total/synth/loop_v2", + RegisterBenchmark(EVMONE_BENCH_NAME(std::string{vm_name} + "/total/synth/loop_v2"), [&vm](State& state) { bench_evmc_execute(state, vm, generate_loop_v2({})); }); } @@ -262,7 +262,8 @@ void register_synthetic_benchmarks() { for (auto& [vm_name, vm] : registered_vms) { - RegisterBenchmark(std::string{vm_name} + "/total/synth/" + to_string(params), + RegisterBenchmark( + EVMONE_BENCH_NAME(std::string{vm_name} + "/total/synth/" + to_string(params)), [&vm, params]( State& state) { bench_evmc_execute(state, vm, generate_code(params)); }) ->Unit(kMicrosecond); diff --git a/test/internal_benchmarks/find_jumpdest_bench.cpp b/test/internal_benchmarks/find_jumpdest_bench.cpp index 337991145b..9f315b9ef4 100644 --- a/test/internal_benchmarks/find_jumpdest_bench.cpp +++ b/test/internal_benchmarks/find_jumpdest_bench.cpp @@ -2,6 +2,7 @@ // Copyright 2019 The evmone Authors. // SPDX-License-Identifier: Apache-2.0 +#include "../utils/bench.hpp" #include #include #include @@ -159,7 +160,7 @@ void find_jumpdest_random(benchmark::State& state) const auto begin = map.data(); benchmark::ClobberMemory(); - while (state.KeepRunningBatch(indexes.size())) + EVMONE_BENCH_LOOP_BATCH(state, indexes.size()) { for (auto i : indexes) { @@ -269,7 +270,7 @@ void find_jumpdest_split_random(benchmark::State& state) const auto value = map.value.data(); benchmark::ClobberMemory(); - while (state.KeepRunningBatch(indexes.size())) + EVMONE_BENCH_LOOP_BATCH(state, indexes.size()) { for (auto i : indexes) { @@ -294,7 +295,7 @@ void find_jumpdest_hashmap_random(benchmark::State& state) const auto hashmap = std::unordered_map{map.begin(), map.end()}; benchmark::ClobberMemory(); - while (state.KeepRunningBatch(indexes.size())) + EVMONE_BENCH_LOOP_BATCH(state, indexes.size()) { for (auto i : indexes) { diff --git a/test/internal_benchmarks/lru_cache_bench.cpp b/test/internal_benchmarks/lru_cache_bench.cpp index 1e332e8bdc..a7efd9c25f 100644 --- a/test/internal_benchmarks/lru_cache_bench.cpp +++ b/test/internal_benchmarks/lru_cache_bench.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "../state/hash_utils.hpp" +#include "../utils/bench.hpp" #include #include #include @@ -108,7 +109,7 @@ void lru_cache_put_empty(benchmark::State& state) data[i] = static_cast(i); benchmark::ClobberMemory(); - while (state.KeepRunningBatch(static_cast(capacity))) + EVMONE_BENCH_LOOP_BATCH(state, static_cast(capacity)) { for (const auto& key : data) { diff --git a/test/internal_benchmarks/modarith_bench.cpp b/test/internal_benchmarks/modarith_bench.cpp index 36032bb4af..cfa4a0552d 100644 --- a/test/internal_benchmarks/modarith_bench.cpp +++ b/test/internal_benchmarks/modarith_bench.cpp @@ -2,6 +2,7 @@ // Copyright 2023 The evmone Authors. // SPDX-License-Identifier: Apache-2.0 +#include "../utils/bench.hpp" #include #include @@ -19,7 +20,7 @@ void modarith_add(benchmark::State& state) auto a = Mod / 2; auto b = Mod / 3; - while (state.KeepRunningBatch(2)) + EVMONE_BENCH_LOOP_BATCH(state, 2) { a = m.add(a, b); b = m.add(b, a); @@ -33,7 +34,7 @@ void modarith_sub(benchmark::State& state) auto a = Mod / 2; auto b = Mod / 3; - while (state.KeepRunningBatch(2)) + EVMONE_BENCH_LOOP_BATCH(state, 2) { a = m.sub(a, b); b = m.sub(b, a); @@ -47,7 +48,7 @@ void modarith_mul(benchmark::State& state) auto a = m.to_mont(Mod / 2); auto b = m.to_mont(Mod / 3); - while (state.KeepRunningBatch(2)) + EVMONE_BENCH_LOOP_BATCH(state, 2) { a = m.mul(a, b); b = m.mul(b, a); diff --git a/test/precompiles_bench/precompiles_bench.cpp b/test/precompiles_bench/precompiles_bench.cpp index c215bdf654..62028ecd58 100644 --- a/test/precompiles_bench/precompiles_bench.cpp +++ b/test/precompiles_bench/precompiles_bench.cpp @@ -2,6 +2,7 @@ // Copyright 2024 The evmone Authors. // SPDX-License-Identifier: Apache-2.0 +#include "../utils/bench.hpp" #include "../utils/utils.hpp" #include #include @@ -214,7 +215,7 @@ void precompile(benchmark::State& state) int64_t total_gas_used = 0; - while (state.KeepRunningBatch(inputs.size())) + EVMONE_BENCH_LOOP_BATCH(state, inputs.size()) { for (const auto& input : inputs) { diff --git a/test/utils/CMakeLists.txt b/test/utils/CMakeLists.txt index 3ed2a3cc65..0203af9bc5 100644 --- a/test/utils/CMakeLists.txt +++ b/test/utils/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources( evmone.testutils PRIVATE stdx/utility.hpp + bench.hpp blob_schedule.hpp blob_schedule.cpp block_transition.hpp diff --git a/test/utils/bench.hpp b/test/utils/bench.hpp new file mode 100644 index 0000000000..0043ac5aa5 --- /dev/null +++ b/test/utils/bench.hpp @@ -0,0 +1,15 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2025 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +/// The benchmark loop for a body processing BATCH_SIZE items per single execution. +/// +/// This is the google/benchmark's State::KeepRunningBatch() loop, but CodSpeed instruments +/// the range-based `for (auto _ : state)` loop only. In the CodSpeed builds the loop body +/// is executed exactly once, so the batch size is irrelevant there. +#ifdef CODSPEED_ENABLED +#define EVMONE_BENCH_LOOP_BATCH(STATE, BATCH_SIZE) for ([[maybe_unused]] auto _ : (STATE)) +#else +#define EVMONE_BENCH_LOOP_BATCH(STATE, BATCH_SIZE) while ((STATE).KeepRunningBatch(BATCH_SIZE)) +#endif From e48cc57bf9939789f4f022aa162abd0eddb32278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Aug 2026 11:03:51 +0200 Subject: [PATCH 02/11] test: Use the codspeed-cpp fork instrumenting the batch loops The KeepRunningBatch() loops are executed but never measured by the released compatibility layer, which silently drops 28 benchmarks, all the precompile ones among them. The fork instruments them, see CodSpeedHQ/codspeed-cpp#54 and the fix in CodSpeedHQ/codspeed-cpp#55, so the benchmark sources no longer need the EVMONE_BENCH_LOOP_BATCH macro switching the loop in the CodSpeed builds. --- test/CMakeLists.txt | 9 +++++---- test/internal_benchmarks/find_jumpdest_bench.cpp | 7 +++---- test/internal_benchmarks/lru_cache_bench.cpp | 3 +-- test/internal_benchmarks/modarith_bench.cpp | 7 +++---- test/precompiles_bench/precompiles_bench.cpp | 3 +-- test/utils/CMakeLists.txt | 1 - test/utils/bench.hpp | 15 --------------- 7 files changed, 13 insertions(+), 32 deletions(-) delete mode 100644 test/utils/bench.hpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3b673e9deb..e06e0f0140 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,13 +24,14 @@ block() URL_HASH SHA256=9631341c82bac4a288bef951f8b26b41f69021794184ece969f8473977eaa340 ) else() - # Replace google/benchmark with CodSpeed's compatibility layer to report the benchmark - # results to https://codspeed.io. It provides the same benchmark::benchmark target, + # Replace google/benchmark with CodSpeed's fork of it to report the benchmark results + # to https://codspeed.io. It provides the same benchmark::benchmark target, # so the benchmark targets need no changes. FetchContent_Declare( benchmark - GIT_REPOSITORY https://github.com/CodSpeedHQ/codspeed-cpp - GIT_TAG f5a917fdd14db7293bd37acb682873fec19f8b6c # v2.4.0 + # Fork of v2.4.0 with fixes not yet available upstream. + GIT_REPOSITORY https://github.com/chfast/codspeed-cpp + GIT_TAG 649071319a5999d5fb02d5abf3f5003e2dd59ef9 GIT_SHALLOW FALSE SOURCE_SUBDIR google_benchmark ) diff --git a/test/internal_benchmarks/find_jumpdest_bench.cpp b/test/internal_benchmarks/find_jumpdest_bench.cpp index 9f315b9ef4..337991145b 100644 --- a/test/internal_benchmarks/find_jumpdest_bench.cpp +++ b/test/internal_benchmarks/find_jumpdest_bench.cpp @@ -2,7 +2,6 @@ // Copyright 2019 The evmone Authors. // SPDX-License-Identifier: Apache-2.0 -#include "../utils/bench.hpp" #include #include #include @@ -160,7 +159,7 @@ void find_jumpdest_random(benchmark::State& state) const auto begin = map.data(); benchmark::ClobberMemory(); - EVMONE_BENCH_LOOP_BATCH(state, indexes.size()) + while (state.KeepRunningBatch(indexes.size())) { for (auto i : indexes) { @@ -270,7 +269,7 @@ void find_jumpdest_split_random(benchmark::State& state) const auto value = map.value.data(); benchmark::ClobberMemory(); - EVMONE_BENCH_LOOP_BATCH(state, indexes.size()) + while (state.KeepRunningBatch(indexes.size())) { for (auto i : indexes) { @@ -295,7 +294,7 @@ void find_jumpdest_hashmap_random(benchmark::State& state) const auto hashmap = std::unordered_map{map.begin(), map.end()}; benchmark::ClobberMemory(); - EVMONE_BENCH_LOOP_BATCH(state, indexes.size()) + while (state.KeepRunningBatch(indexes.size())) { for (auto i : indexes) { diff --git a/test/internal_benchmarks/lru_cache_bench.cpp b/test/internal_benchmarks/lru_cache_bench.cpp index a7efd9c25f..1e332e8bdc 100644 --- a/test/internal_benchmarks/lru_cache_bench.cpp +++ b/test/internal_benchmarks/lru_cache_bench.cpp @@ -3,7 +3,6 @@ // SPDX-License-Identifier: Apache-2.0 #include "../state/hash_utils.hpp" -#include "../utils/bench.hpp" #include #include #include @@ -109,7 +108,7 @@ void lru_cache_put_empty(benchmark::State& state) data[i] = static_cast(i); benchmark::ClobberMemory(); - EVMONE_BENCH_LOOP_BATCH(state, static_cast(capacity)) + while (state.KeepRunningBatch(static_cast(capacity))) { for (const auto& key : data) { diff --git a/test/internal_benchmarks/modarith_bench.cpp b/test/internal_benchmarks/modarith_bench.cpp index cfa4a0552d..36032bb4af 100644 --- a/test/internal_benchmarks/modarith_bench.cpp +++ b/test/internal_benchmarks/modarith_bench.cpp @@ -2,7 +2,6 @@ // Copyright 2023 The evmone Authors. // SPDX-License-Identifier: Apache-2.0 -#include "../utils/bench.hpp" #include #include @@ -20,7 +19,7 @@ void modarith_add(benchmark::State& state) auto a = Mod / 2; auto b = Mod / 3; - EVMONE_BENCH_LOOP_BATCH(state, 2) + while (state.KeepRunningBatch(2)) { a = m.add(a, b); b = m.add(b, a); @@ -34,7 +33,7 @@ void modarith_sub(benchmark::State& state) auto a = Mod / 2; auto b = Mod / 3; - EVMONE_BENCH_LOOP_BATCH(state, 2) + while (state.KeepRunningBatch(2)) { a = m.sub(a, b); b = m.sub(b, a); @@ -48,7 +47,7 @@ void modarith_mul(benchmark::State& state) auto a = m.to_mont(Mod / 2); auto b = m.to_mont(Mod / 3); - EVMONE_BENCH_LOOP_BATCH(state, 2) + while (state.KeepRunningBatch(2)) { a = m.mul(a, b); b = m.mul(b, a); diff --git a/test/precompiles_bench/precompiles_bench.cpp b/test/precompiles_bench/precompiles_bench.cpp index 62028ecd58..c215bdf654 100644 --- a/test/precompiles_bench/precompiles_bench.cpp +++ b/test/precompiles_bench/precompiles_bench.cpp @@ -2,7 +2,6 @@ // Copyright 2024 The evmone Authors. // SPDX-License-Identifier: Apache-2.0 -#include "../utils/bench.hpp" #include "../utils/utils.hpp" #include #include @@ -215,7 +214,7 @@ void precompile(benchmark::State& state) int64_t total_gas_used = 0; - EVMONE_BENCH_LOOP_BATCH(state, inputs.size()) + while (state.KeepRunningBatch(inputs.size())) { for (const auto& input : inputs) { diff --git a/test/utils/CMakeLists.txt b/test/utils/CMakeLists.txt index 0203af9bc5..3ed2a3cc65 100644 --- a/test/utils/CMakeLists.txt +++ b/test/utils/CMakeLists.txt @@ -14,7 +14,6 @@ target_sources( evmone.testutils PRIVATE stdx/utility.hpp - bench.hpp blob_schedule.hpp blob_schedule.cpp block_transition.hpp diff --git a/test/utils/bench.hpp b/test/utils/bench.hpp deleted file mode 100644 index 0043ac5aa5..0000000000 --- a/test/utils/bench.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// evmone: Fast Ethereum Virtual Machine implementation -// Copyright 2025 The evmone Authors. -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -/// The benchmark loop for a body processing BATCH_SIZE items per single execution. -/// -/// This is the google/benchmark's State::KeepRunningBatch() loop, but CodSpeed instruments -/// the range-based `for (auto _ : state)` loop only. In the CodSpeed builds the loop body -/// is executed exactly once, so the batch size is irrelevant there. -#ifdef CODSPEED_ENABLED -#define EVMONE_BENCH_LOOP_BATCH(STATE, BATCH_SIZE) for ([[maybe_unused]] auto _ : (STATE)) -#else -#define EVMONE_BENCH_LOOP_BATCH(STATE, BATCH_SIZE) while ((STATE).KeepRunningBatch(BATCH_SIZE)) -#endif From 8e5246536e8b157501200ac36522e5c0a9cc7a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Aug 2026 14:13:03 +0200 Subject: [PATCH 03/11] test: Benchmark the baseline VM and the mainnet precompiles only The synthetic benchmarks, the advanced and bnocgoto VM variants and the internal benchmarks are dropped from the CodSpeed runs: 920 benchmarks is more than the reports can be read for, and the two remaining shards cover what the changes are judged by, the baseline VM on the mainnet-derived programs (41) and the precompiles on the mainnet inputs (8). --- .github/workflows/codspeed.yml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index ccb1da39db..014274d518 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -40,7 +40,7 @@ jobs: -DCODSPEED_MODE=simulation - name: Build - run: cmake --build $BUILD_DIR --target evmone-bench evmone-bench-internal evmone-precompiles-bench + run: cmake --build $BUILD_DIR --target evmone-bench evmone-precompiles-bench - name: Upload benchmark executables uses: actions/upload-artifact@v7 @@ -62,18 +62,10 @@ jobs: # CodSpeed aggregates the results of all the shards of a single workflow run. matrix: include: - - name: synth - run: bin/evmone-bench --benchmark_filter=synth - - name: micro - run: bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter=micro - - name: main - run: bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter='main/(blake2b|sha1|structarray|swap_math|weierstrudel)' - - name: snailtracer - run: bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter=main/snailtracer - - name: internal - run: bin/evmone-bench-internal + - name: baseline + run: bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter='baseline/(analyse|execute)' - name: precompiles - run: bin/evmone-precompiles-bench + run: bin/evmone-precompiles-bench --benchmark_filter=PrecompileId steps: - uses: actions/checkout@v5 with: From c95671dac00f8a5c3afbc188f4a367d7b8b79349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Aug 2026 16:44:58 +0200 Subject: [PATCH 04/11] test: Bump the codspeed-cpp fork to keep the anonymous namespace out of the URIs --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e06e0f0140..38a98a8bbc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -31,7 +31,7 @@ block() benchmark # Fork of v2.4.0 with fixes not yet available upstream. GIT_REPOSITORY https://github.com/chfast/codspeed-cpp - GIT_TAG 649071319a5999d5fb02d5abf3f5003e2dd59ef9 + GIT_TAG 0ecdd6e7d8f9e858e8e0b2fbe54ff7f427bec528 GIT_SHALLOW FALSE SOURCE_SUBDIR google_benchmark ) From 8582cf22e682927107a845acf117956ccf92b5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Aug 2026 16:56:27 +0200 Subject: [PATCH 05/11] test: Run the CodSpeed benchmarks in a single job Building once and running both benchmark executables in the same job removes the artifact round trip, the executable permission fixup it needs, the second checkout and the matrix. The shards were not worth parallelizing: together they take less than the build. --- .github/workflows/codspeed.yml | 57 ++++++++-------------------------- 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index 014274d518..b78df78ddf 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -13,17 +13,17 @@ on: # performance analysis in order to generate initial data. workflow_dispatch: -permissions: - contents: read - env: BUILD_DIR: build CMAKE_BUILD_PARALLEL_LEVEL: 4 jobs: - build: - name: Build benchmarks + benchmark: + name: Benchmark runs-on: ubuntu-latest + permissions: + contents: read # required for actions/checkout + id-token: write # required for OIDC authentication with CodSpeed steps: - uses: actions/checkout@v5 with: @@ -42,47 +42,16 @@ jobs: - name: Build run: cmake --build $BUILD_DIR --target evmone-bench evmone-precompiles-bench - - name: Upload benchmark executables - uses: actions/upload-artifact@v7 - with: - name: benchmarks - path: ${{ env.BUILD_DIR }}/bin/ - retention-days: 1 - - benchmark: - name: Benchmark ${{ matrix.name }} - needs: build - runs-on: ubuntu-latest - permissions: - contents: read # required for actions/checkout - id-token: write # required for OIDC authentication with CodSpeed - strategy: - fail-fast: false - # The benchmarks are split into shards executed in parallel. - # CodSpeed aggregates the results of all the shards of a single workflow run. - matrix: - include: - - name: baseline - run: bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter='baseline/(analyse|execute)' - - name: precompiles - run: bin/evmone-precompiles-bench --benchmark_filter=PrecompileId - steps: - - uses: actions/checkout@v5 - with: - submodules: recursive - - - name: Download benchmark executables - uses: actions/download-artifact@v7 + # CodSpeed aggregates the results of all the runs of a single workflow run. + - name: Benchmark the baseline VM + uses: CodSpeedHQ/action@v5 with: - name: benchmarks - path: bin - - - name: Make the benchmark executables executable - # The executable permission is not preserved by the artifact upload. - run: chmod +x bin/* + mode: simulation + run: ${{ env.BUILD_DIR }}/bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter='baseline/(analyse|execute)' - - name: Run benchmarks + - name: Benchmark the precompiles uses: CodSpeedHQ/action@v5 with: mode: simulation - run: ${{ matrix.run }} + # The file part of the URI contains "precompile" as well, hence the "::". + run: ${{ env.BUILD_DIR }}/bin/evmone-precompiles-bench --benchmark_filter=::precompile From eceafe0b384409edb98bae14bb9374daa8436d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Aug 2026 17:01:37 +0200 Subject: [PATCH 06/11] test: Pin the CodSpeed job to Ubuntu 24.04 CodSpeed provides its instrumented Valgrind for Ubuntu 22.04, Ubuntu 24.04 and Debian 12 only, so the job breaks with "Unsupported system" once ubuntu-latest moves on. --- .github/workflows/codspeed.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index b78df78ddf..ad73ffd7a3 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -20,7 +20,9 @@ env: jobs: benchmark: name: Benchmark - runs-on: ubuntu-latest + # CodSpeed ships its instrumented Valgrind for Ubuntu 22.04, Ubuntu 24.04 and Debian 12 only, + # and bails out with "Unsupported system" anywhere else, so the image cannot be `latest`. + runs-on: ubuntu-24.04 permissions: contents: read # required for actions/checkout id-token: write # required for OIDC authentication with CodSpeed From 0e8eae4b1828b775b17633580ebeedb3b43f5ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Aug 2026 17:06:24 +0200 Subject: [PATCH 07/11] test: Build the CodSpeed benchmarks with GCC 14 The newest GCC available on the ubuntu-24.04 image the job is pinned to, which otherwise defaults to GCC 13. --- .github/workflows/codspeed.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index ad73ffd7a3..682556117a 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -16,6 +16,9 @@ on: env: BUILD_DIR: build CMAKE_BUILD_PARALLEL_LEVEL: 4 + # The newest GCC on the ubuntu-24.04 image, which otherwise defaults to GCC 13. + CC: gcc-14 + CXX: g++-14 jobs: benchmark: From 25308e2eb13765b48fbd96a542596f0ce1eb2a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 14 Aug 2026 19:18:37 +0200 Subject: [PATCH 08/11] test: Benchmark all the precompile cases, including the modexp sweep The mainnet modexp inputs all have an odd 256-bit modulus, so they exercise a single code path: neither the exponent reduction for the power-of-two part of the modulus nor anything specific to the moduli of other sizes is visible in them. The GMP and libsecp256k1 implementations are built too, to keep their results next to the evmone ones. --- .github/workflows/codspeed.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index 682556117a..e12affb1f3 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -34,6 +34,9 @@ jobs: with: submodules: recursive + - name: Install GMP + run: sudo apt-get -q update && sudo apt-get -qy install libgmp-dev + - name: Configure # RelWithDebInfo keeps the optimizations on and adds the debug information # needed by CodSpeed to attribute the measurements to the source code. @@ -42,6 +45,8 @@ jobs: -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_SHARED_LIBS=OFF -DEVMONE_TESTING=ON + -DEVMONE_PRECOMPILES_GMP=ON + -DEVMONE_PRECOMPILES_LIBSECP256K1=ON -DCODSPEED_MODE=simulation - name: Build @@ -54,9 +59,10 @@ jobs: mode: simulation run: ${{ env.BUILD_DIR }}/bin/evmone-bench test/evm-benchmarks/benchmarks --benchmark_filter='baseline/(analyse|execute)' + # Both the mainnet inputs and the modexp parameter sweep: the mainnet moduli are all odd + # and 256-bit, so they cover a single code path and hide the work done on the others. - name: Benchmark the precompiles uses: CodSpeedHQ/action@v5 with: mode: simulation - # The file part of the URI contains "precompile" as well, hence the "::". - run: ${{ env.BUILD_DIR }}/bin/evmone-precompiles-bench --benchmark_filter=::precompile + run: ${{ env.BUILD_DIR }}/bin/evmone-precompiles-bench From 23ff4c4ae1eef27329671100ea8a793133eeadfc Mon Sep 17 00:00:00 2001 From: CodSpeed Bot Date: Fri, 14 Aug 2026 18:37:00 +0000 Subject: [PATCH 09/11] test: Replace the EVMONE_BENCH_NAME macro with bench_name() The default std::source_location argument is evaluated at the call site, so the URI keeps naming the file which registers the benchmark. --- test/bench/bench.cpp | 16 +++++++--------- test/bench/helpers.hpp | 21 +++++++++++++-------- test/bench/synthetic_benchmarks.cpp | 6 +++--- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/test/bench/bench.cpp b/test/bench/bench.cpp index fc757f3cc2..f6ef1e40e2 100644 --- a/test/bench/bench.cpp +++ b/test/bench/bench.cpp @@ -116,7 +116,7 @@ void register_benchmarks(std::span benchmark_cases) { if (advanced_vm != nullptr) { - RegisterBenchmark(EVMONE_BENCH_NAME("advanced/analyse/" + b.name), [&b](State& state) { + RegisterBenchmark(bench_name("advanced/analyse/" + b.name), [&b](State& state) { bench_analyse( state, default_revision, b.code); })->Unit(kMicrosecond); @@ -124,7 +124,7 @@ void register_benchmarks(std::span benchmark_cases) if (baseline_vm != nullptr) { - RegisterBenchmark(EVMONE_BENCH_NAME("baseline/analyse/" + b.name), [&b](State& state) { + RegisterBenchmark(bench_name("baseline/analyse/" + b.name), [&b](State& state) { bench_analyse( state, default_revision, b.code); })->Unit(kMicrosecond); @@ -136,7 +136,7 @@ void register_benchmarks(std::span benchmark_cases) if (advanced_vm != nullptr) { - const auto name = EVMONE_BENCH_NAME("advanced/execute/" + case_name); + const auto name = bench_name("advanced/execute/" + case_name); RegisterBenchmark(name, [&vm = *advanced_vm, &b, &input](State& state) { bench_advanced_execute(state, vm, b.code, input.input, input.expected_output); })->Unit(kMicrosecond); @@ -144,7 +144,7 @@ void register_benchmarks(std::span benchmark_cases) if (baseline_vm != nullptr) { - const auto name = EVMONE_BENCH_NAME("baseline/execute/" + case_name); + const auto name = bench_name("baseline/execute/" + case_name); RegisterBenchmark(name, [&vm = *baseline_vm, &b, &input](State& state) { bench_baseline_execute(state, vm, b.code, input.input, input.expected_output); })->Unit(kMicrosecond); @@ -152,7 +152,7 @@ void register_benchmarks(std::span benchmark_cases) if (basel_cg_vm != nullptr) { - const auto name = EVMONE_BENCH_NAME("bnocgoto/execute/" + case_name); + const auto name = bench_name("bnocgoto/execute/" + case_name); RegisterBenchmark(name, [&vm = *basel_cg_vm, &b, &input](State& state) { bench_baseline_execute(state, vm, b.code, input.input, input.expected_output); })->Unit(kMicrosecond); @@ -160,7 +160,7 @@ void register_benchmarks(std::span benchmark_cases) for (auto& [vm_name, vm] : registered_vms) { - const auto name = EVMONE_BENCH_NAME(std::string{vm_name} + "/total/" + case_name); + const auto name = bench_name(std::string{vm_name} + "/total/" + case_name); RegisterBenchmark(name, [&vm, &b, &input](State& state) { bench_evmc_execute(state, vm, b.code, input.input, input.expected_output); })->Unit(kMicrosecond); @@ -235,9 +235,7 @@ std::tuple> parseargs(int argc, char** argv) int main(int argc, char** argv) { #ifndef CODSPEED_ENABLED - // Not available in the google/benchmark version the CodSpeed compatibility - // layer is based on. Also not needed there: the measurements are done by - // CodSpeed itself. + // Not available in the google/benchmark version CodSpeed's fork is based on, nor needed there. MaybeReenterWithoutASLR(argc, argv); #endif diff --git a/test/bench/helpers.hpp b/test/bench/helpers.hpp index 60102a9b89..650fa541b4 100644 --- a/test/bench/helpers.hpp +++ b/test/bench/helpers.hpp @@ -11,20 +11,25 @@ #include #include #include +#include + +namespace evmone::test +{ +extern std::map registered_vms; /// Decorates a dynamically registered benchmark name with the location of the registration. /// CodSpeed identifies benchmarks by the "source_file::name" URI, which the BENCHMARK() macro -/// provides automatically, but RegisterBenchmark() does not. Without CodSpeed this is a no-op. +/// adds automatically, but RegisterBenchmark() does not. Without CodSpeed this is a no-op. +/// The default argument is evaluated at the call site, naming the file registering the benchmark. +inline std::string bench_name(std::string name, + [[maybe_unused]] const std::source_location loc = std::source_location::current()) +{ #ifdef CODSPEED_ENABLED -#define EVMONE_BENCH_NAME(NAME) \ - (::codspeed::get_path_relative_to_workspace(__FILE__) + "::" + (NAME)) + return codspeed::get_path_relative_to_workspace(loc.file_name()) + "::" + std::move(name); #else -#define EVMONE_BENCH_NAME(NAME) (NAME) + return name; #endif - -namespace evmone::test -{ -extern std::map registered_vms; +} constexpr auto default_revision = EVMC_ISTANBUL; constexpr auto default_gas_limit = std::numeric_limits::max(); diff --git a/test/bench/synthetic_benchmarks.cpp b/test/bench/synthetic_benchmarks.cpp index 14891744a0..f564bd363d 100644 --- a/test/bench/synthetic_benchmarks.cpp +++ b/test/bench/synthetic_benchmarks.cpp @@ -252,9 +252,9 @@ void register_synthetic_benchmarks() for (auto& [vm_name, vm] : registered_vms) { - RegisterBenchmark(EVMONE_BENCH_NAME(std::string{vm_name} + "/total/synth/loop_v1"), + RegisterBenchmark(bench_name(std::string{vm_name} + "/total/synth/loop_v1"), [&vm](State& state) { bench_evmc_execute(state, vm, generate_loop_v1({})); }); - RegisterBenchmark(EVMONE_BENCH_NAME(std::string{vm_name} + "/total/synth/loop_v2"), + RegisterBenchmark(bench_name(std::string{vm_name} + "/total/synth/loop_v2"), [&vm](State& state) { bench_evmc_execute(state, vm, generate_loop_v2({})); }); } @@ -263,7 +263,7 @@ void register_synthetic_benchmarks() for (auto& [vm_name, vm] : registered_vms) { RegisterBenchmark( - EVMONE_BENCH_NAME(std::string{vm_name} + "/total/synth/" + to_string(params)), + bench_name(std::string{vm_name} + "/total/synth/" + to_string(params)), [&vm, params]( State& state) { bench_evmc_execute(state, vm, generate_code(params)); }) ->Unit(kMicrosecond); From 7d7c6d4e28671d99b55e4a740add027f4ff2d296 Mon Sep 17 00:00:00 2001 From: CodSpeed Bot Date: Fri, 14 Aug 2026 18:37:00 +0000 Subject: [PATCH 10/11] ci: Build the CodSpeed benchmarks with -O3 -g --- .github/workflows/codspeed.yml | 11 +++++++---- README.md | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index e12affb1f3..009b448c39 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -1,5 +1,5 @@ # evmone: Fast Ethereum Virtual Machine implementation -# Copyright 2025 The evmone Authors. +# Copyright 2026 The evmone Authors. # SPDX-License-Identifier: Apache-2.0 name: CodSpeed @@ -38,11 +38,14 @@ jobs: run: sudo apt-get -q update && sudo apt-get -qy install libgmp-dev - name: Configure - # RelWithDebInfo keeps the optimizations on and adds the debug information - # needed by CodSpeed to attribute the measurements to the source code. + # The Release build type keeps the -O3 optimizations on, -g adds the debug information + # needed by CodSpeed to attribute the measurements to the source code. CodSpeed recommends + # (and warns about) RelWithDebInfo, but that would downgrade the optimizations to -O2. run: > cmake -S . -B $BUILD_DIR - -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_C_FLAGS=-g + -DCMAKE_CXX_FLAGS=-g -DBUILD_SHARED_LIBS=OFF -DEVMONE_TESTING=ON -DEVMONE_PRECOMPILES_GMP=ON diff --git a/README.md b/README.md index 1c127a110d..59d072eadb 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ Licensed under the [Apache License, Version 2.0]. [appveyor]: https://ci.appveyor.com/project/chfast/evmone/branch/master [circleci]: https://circleci.com/gh/ethereum/evmone/tree/master [codecov]: https://codecov.io/gh/ethereum/evmone/ -[codspeed]: https://app.codspeed.io/ipsilon/evmone?utm_source=badge +[codspeed]: https://app.codspeed.io/ipsilon/evmone [Apache License, Version 2.0]: LICENSE [ethereum]: https://ethereum.org [EVMC]: https://github.com/ethereum/evmc From 32b2af768f5eedea0fd5454606c67fcee3f33b3d Mon Sep 17 00:00:00 2001 From: CodSpeed Bot Date: Sat, 15 Aug 2026 13:32:59 +0000 Subject: [PATCH 11/11] test: Select the benchmark library targets explicitly The set of the targets is known in the branch which fetches them, so list it there instead of probing for the target existence afterwards. --- test/CMakeLists.txt | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 38a98a8bbc..b8105f8238 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,10 +13,11 @@ find_package(CLI11 CONFIG REQUIRED) hunter_add_package(GTest) find_package(GTest CONFIG REQUIRED) -block() +block(PROPAGATE benchmark_libs) set(BUILD_SHARED_LIBS OFF) set(BENCHMARK_ENABLE_TESTING OFF) set(BENCHMARK_ENABLE_INSTALL OFF) + set(benchmark_libs benchmark benchmark_main) if(NOT CODSPEED_MODE) FetchContent_Declare( benchmark @@ -35,21 +36,18 @@ block() GIT_SHALLOW FALSE SOURCE_SUBDIR google_benchmark ) + list(APPEND benchmark_libs codspeed instrument_hooks) endif() FetchContent_MakeAvailable(benchmark) endblock() -foreach(TARGET IN ITEMS benchmark benchmark_main codspeed instrument_hooks) - if(TARGET ${TARGET}) - set_target_properties( - ${TARGET} PROPERTIES - COMPILE_OPTIONS "$<$:-w>;$<$:-w>" - C_CLANG_TIDY "" - CXX_CLANG_TIDY "" - SYSTEM TRUE # TODO(cmake-3.26): Use the SYSTEM option of FetchContent_Declare(). - ) - endif() -endforeach() +set_target_properties( + ${benchmark_libs} PROPERTIES + COMPILE_OPTIONS "$<$:-w>;$<$:-w>" + C_CLANG_TIDY "" + CXX_CLANG_TIDY "" + SYSTEM TRUE # TODO(cmake-3.26): Use the SYSTEM option of FetchContent_Declare(). +) include(CableBuildInfo) cable_add_buildinfo_library(PROJECT_NAME evmone)