mirror of
https://github.com/gunchev/bench.git
synced 2026-02-19 18:23:30 +00:00
Update 2026-02-07
This commit is contained in:
parent
b6930e02c5
commit
6526f7ae04
6 changed files with 125 additions and 38 deletions
|
|
@ -1,13 +1,13 @@
|
||||||
cmake_minimum_required(VERSION 3.20.0) # RHEL 8
|
cmake_minimum_required(VERSION 3.20.0) # RHEL 8
|
||||||
|
|
||||||
project(benchmarks
|
project(benchmarks
|
||||||
VERSION 0.0.0.1 # PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH, and PROJECT_VERSION_TWEAK.
|
VERSION 0.0.1.0 # PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH, and PROJECT_VERSION_TWEAK.
|
||||||
DESCRIPTION "Various benchmarks"
|
DESCRIPTION "Various benchmarks"
|
||||||
HOMEPAGE_URL "https://github.com/gunchev/bench/"
|
HOMEPAGE_URL "https://github.com/gunchev/bench/"
|
||||||
LANGUAGES C CXX)
|
LANGUAGES C CXX)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED TRUE)
|
set(CMAKE_C_STANDARD_REQUIRED TRUE)
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||||
|
|
||||||
# set(CMAKE_VERBOSE_MAKEFILE TRUE) # or "cd build; make VERBOSE=1"
|
# set(CMAKE_VERBOSE_MAKEFILE TRUE) # or "cd build; make VERBOSE=1"
|
||||||
|
|
@ -18,6 +18,9 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||||
"Choose the type of build, options are: Debug DebugCov RelWithDebInfo Release MinSizeRel." FORCE)
|
"Choose the type of build, options are: Debug DebugCov RelWithDebInfo Release MinSizeRel." FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
|
||||||
# SOVERSION is ignored if NO_SONAME property is set.
|
# SOVERSION is ignored if NO_SONAME property is set.
|
||||||
# "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${PROJECT_VERSION_TWEAK}"
|
# "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${PROJECT_VERSION_TWEAK}"
|
||||||
set(${PROJECT_NAME}_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
set(${PROJECT_NAME}_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||||
|
|
@ -47,19 +50,14 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
|
||||||
# Compiler/linker flags
|
# Compiler/linker flags
|
||||||
if(EXISTS "/etc/fedora-release")
|
|
||||||
set(CMAKE_C_FLAGS "-Wall -Wextra")
|
|
||||||
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
|
|
||||||
else()
|
|
||||||
set(CMAKE_C_FLAGS "-Wall -Wextra -Werror")
|
set(CMAKE_C_FLAGS "-Wall -Wextra -Werror")
|
||||||
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Werror")
|
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Werror")
|
||||||
endif()
|
|
||||||
|
# https://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html#Template-Instantiation
|
||||||
|
|
||||||
include(CheckCCompilerFlag)
|
include(CheckCCompilerFlag)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
|
||||||
# https://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html#Template-Instantiation
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_QUIET_OLD ${CMAKE_REQUIRED_QUIET})
|
set(CMAKE_REQUIRED_QUIET_OLD ${CMAKE_REQUIRED_QUIET})
|
||||||
set(CMAKE_REQUIRED_QUIET ON)
|
set(CMAKE_REQUIRED_QUIET ON)
|
||||||
macro(CheckAndAddFlag flag)
|
macro(CheckAndAddFlag flag)
|
||||||
|
|
@ -120,20 +118,24 @@ set(CMAKE_C_FLAGS_MINSIZEREL "-Os -ggdb3 -D_FORTIFY_SOURCE=2 -DN
|
||||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -ggdb3 -D_FORTIFY_SOURCE=2 -DNDEBUG")
|
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -ggdb3 -D_FORTIFY_SOURCE=2 -DNDEBUG")
|
||||||
|
|
||||||
|
|
||||||
|
# Google benchmark
|
||||||
|
find_package(benchmark 1.9.4)
|
||||||
|
if (NOT benchmark_FOUND)
|
||||||
|
message(STATUS "Google Benchmark not found, fetching it...")
|
||||||
|
|
||||||
# Enable testing?
|
FetchContent_Declare(
|
||||||
include(FindPkgConfig)
|
benchmark
|
||||||
pkg_check_modules(CPPUNIT cppunit>=1.14.0) # REQUIRED
|
GIT_REPOSITORY https://github.com/google/benchmark.git
|
||||||
if(CPPUNIT_FOUND)
|
GIT_TAG v1.9.4
|
||||||
enable_testing()
|
)
|
||||||
include(CTest)
|
|
||||||
find_program(CTEST_COVERAGE_COMMAND NAMES gcov)
|
# Disable benchmark's own tests
|
||||||
find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind)
|
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
|
||||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(benchmark)
|
||||||
endif()
|
endif()
|
||||||
|
message(STATUS "Found Google benchmark version: ${benchmark_VERSION}")
|
||||||
|
|
||||||
find_package(benchmark REQUIRED)
|
|
||||||
|
|
||||||
# Threads library
|
# Threads library
|
||||||
# set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
# set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||||
|
|
@ -145,8 +147,29 @@ find_package(benchmark REQUIRED)
|
||||||
|
|
||||||
# pkg_check_modules(HIREDIS REQUIRED hiredis>=1.0.2)
|
# pkg_check_modules(HIREDIS REQUIRED hiredis>=1.0.2)
|
||||||
|
|
||||||
|
# Enable testing?
|
||||||
|
#include(FindPkgConfig)
|
||||||
|
#pkg_check_modules(CPPUNIT cppunit>=1.14.0) # REQUIRED
|
||||||
|
# set(GTEST_MIN_VERSION 1.13.0)
|
||||||
|
# find_package(GTest ${GTEST_MIN_VERSION} QUIET)
|
||||||
|
# if (NOT GTest_FOUND)
|
||||||
|
# message(STATUS "GoogleTest not found, fetching it...")
|
||||||
|
# FetchContent_Declare(
|
||||||
|
# googletest
|
||||||
|
# GIT_REPOSITORY https://github.com/google/googletest.git
|
||||||
|
# GIT_TAG v1.14.0
|
||||||
|
# )
|
||||||
|
# # Don't install or build gtest's own tests
|
||||||
|
# set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
|
||||||
|
# set(BUILD_GMOCK OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
# FetchContent_MakeAvailable(googletest)
|
||||||
|
# endif()
|
||||||
|
|
||||||
|
|
||||||
# include_directories(src)
|
# include_directories(src)
|
||||||
|
|
||||||
add_executable(transform src/transform.cpp)
|
add_executable(transform src/transform.cpp)
|
||||||
target_link_libraries(transform PRIVATE benchmark::benchmark) # fmt::fmt Threads::Threads)
|
target_link_libraries(transform PRIVATE benchmark::benchmark) # fmt::fmt Threads::Threads)
|
||||||
|
target_compile_features(transform PRIVATE cxx_std_17)
|
||||||
install(TARGETS transform DESTINATION bin)
|
install(TARGETS transform DESTINATION bin)
|
||||||
|
|
|
||||||
57
README.md
57
README.md
|
|
@ -4,4 +4,59 @@
|
||||||
Various C++ benchmarks:
|
Various C++ benchmarks:
|
||||||
|
|
||||||
- transform.cpp - benchmark std::transform vs loop and custom lowercase and tolower
|
- transform.cpp - benchmark std::transform vs loop and custom lowercase and tolower
|
||||||

|
|
||||||
|
---
|
||||||
|
```shell
|
||||||
|
$ make releasec # clang++ 21.1.8
|
||||||
|
$ ./build/releasec/transform
|
||||||
|
```
|
||||||
|
|
||||||
|
2026-02-07T15:43:00+02:00
|
||||||
|
Running ./build/releasec/transform
|
||||||
|
Run on (32 X 5187.5 MHz CPU s)
|
||||||
|
CPU Caches:
|
||||||
|
L1 Data 48 KiB (x16)
|
||||||
|
L1 Instruction 32 KiB (x16)
|
||||||
|
L2 Unified 1024 KiB (x16)
|
||||||
|
L3 Unified 32768 KiB (x2)
|
||||||
|
Load Average: 0.58, 0.53, 0.60
|
||||||
|
***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.
|
||||||
|
***WARNING*** ASLR is enabled, the results may have unreproducible noise in them.
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Benchmark Time CPU Iterations
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
algorithm_lowercase_my 17.8 ns 17.7 ns 39664595
|
||||||
|
loop_lowercase_my 31.9 ns 31.9 ns 22028280
|
||||||
|
algorithm_lowercase_toupper 79.3 ns 79.2 ns 8838048
|
||||||
|
loop_lowercase_toupper 69.7 ns 69.5 ns 9977740
|
||||||
|
---
|
||||||
|
```shell
|
||||||
|
$ make release # g++ 15.2.1
|
||||||
|
$ ./build/release/transform
|
||||||
|
```
|
||||||
|
|
||||||
|
2026-02-07T15:43:03+02:00
|
||||||
|
Running ./build/release/transform
|
||||||
|
Run on (32 X 5187.5 MHz CPU s)
|
||||||
|
CPU Caches:
|
||||||
|
L1 Data 48 KiB (x16)
|
||||||
|
L1 Instruction 32 KiB (x16)
|
||||||
|
L2 Unified 1024 KiB (x16)
|
||||||
|
L3 Unified 32768 KiB (x2)
|
||||||
|
Load Average: 0.61, 0.54, 0.60
|
||||||
|
***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.
|
||||||
|
***WARNING*** ASLR is enabled, the results may have unreproducible noise in them.
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Benchmark Time CPU Iterations
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
algorithm_lowercase_my 17.7 ns 17.7 ns 33607332
|
||||||
|
loop_lowercase_my 28.2 ns 28.2 ns 24781013
|
||||||
|
algorithm_lowercase_toupper 77.1 ns 77.0 ns 9116098
|
||||||
|
loop_lowercase_toupper 65.5 ns 65.4 ns 10687636
|
||||||
|
---
|
||||||
|
|
||||||
|
<img src="bench_lowercase_gcc13_cpp23.png" alt="gcc13" style="width:98%;"/>
|
||||||
|
|
||||||
|
<img src="bench_lowercase_clang17_cpp23.png" alt="clang17" style="width:98%;"/>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB |
BIN
bench_lowercase_clang17_cpp23.png
Normal file
BIN
bench_lowercase_clang17_cpp23.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 134 KiB |
BIN
bench_lowercase_gcc13_cpp23.png
Normal file
BIN
bench_lowercase_gcc13_cpp23.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
|
|
@ -3,13 +3,16 @@
|
||||||
#include <benchmark/benchmark.h>
|
#include <benchmark/benchmark.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sysexits.h>
|
#include <sysexits.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
const char* data = "Hello world, to be or not to be a long string, that is the question!";
|
const char* data = "Hello world, to be or not to be a long string, that is the question!";
|
||||||
|
|
||||||
static void algorithm_lowercase_my(benchmark::State& state) {
|
static void algorithm_lowercase_my(benchmark::State& state) {
|
||||||
|
std::string name;
|
||||||
|
name.reserve(strlen(data));
|
||||||
for (auto _ : state) { // Code inside this loop is measured repeatedly
|
for (auto _ : state) { // Code inside this loop is measured repeatedly
|
||||||
std::string name = data;
|
name = data;
|
||||||
std::transform(name.cbegin(), name.cend(), name.begin(), [](char c) noexcept {
|
std::transform(name.cbegin(), name.cend(), name.begin(), [](char c) noexcept {
|
||||||
return (c >= 'a' && c <= 'z') ? c = c - 'a' + 'A' : c;
|
return (c >= 'a' && c <= 'z') ? c = c - 'a' + 'A' : c;
|
||||||
});
|
});
|
||||||
|
|
@ -19,8 +22,10 @@ static void algorithm_lowercase_my(benchmark::State& state) {
|
||||||
BENCHMARK(algorithm_lowercase_my); // Register the function as a benchmark
|
BENCHMARK(algorithm_lowercase_my); // Register the function as a benchmark
|
||||||
|
|
||||||
static void loop_lowercase_my(benchmark::State& state) {
|
static void loop_lowercase_my(benchmark::State& state) {
|
||||||
|
std::string name;
|
||||||
|
name.reserve(strlen(data));
|
||||||
for (auto _ : state) { // Code before the loop is not measured
|
for (auto _ : state) { // Code before the loop is not measured
|
||||||
std::string name = data;
|
name = data;
|
||||||
for (char& c : name) {
|
for (char& c : name) {
|
||||||
if (c >= 'a' && c <= 'z') {
|
if (c >= 'a' && c <= 'z') {
|
||||||
c = c - 'a' + 'A';
|
c = c - 'a' + 'A';
|
||||||
|
|
@ -33,8 +38,10 @@ BENCHMARK(loop_lowercase_my); // Register the function as a benchmark
|
||||||
|
|
||||||
|
|
||||||
static void algorithm_lowercase_toupper(benchmark::State& state) {
|
static void algorithm_lowercase_toupper(benchmark::State& state) {
|
||||||
|
std::string name;
|
||||||
|
name.reserve(strlen(data));
|
||||||
for (auto _ : state) { // Code inside this loop is measured repeatedly
|
for (auto _ : state) { // Code inside this loop is measured repeatedly
|
||||||
std::string name = data;
|
name = data;
|
||||||
std::transform(name.cbegin(), name.cend(), name.begin(), [](char c) noexcept {
|
std::transform(name.cbegin(), name.cend(), name.begin(), [](char c) noexcept {
|
||||||
return std::toupper(static_cast<unsigned char>(c));
|
return std::toupper(static_cast<unsigned char>(c));
|
||||||
});
|
});
|
||||||
|
|
@ -44,6 +51,21 @@ static void algorithm_lowercase_toupper(benchmark::State& state) {
|
||||||
BENCHMARK(algorithm_lowercase_toupper); // Register the function as a benchmark
|
BENCHMARK(algorithm_lowercase_toupper); // Register the function as a benchmark
|
||||||
|
|
||||||
|
|
||||||
|
static void loop_lowercase_toupper(benchmark::State& state) {
|
||||||
|
std::string name;
|
||||||
|
name.reserve(strlen(data));
|
||||||
|
for (auto _ : state) { // Code inside this loop is measured repeatedly
|
||||||
|
name = data;
|
||||||
|
for (char& c : name) {
|
||||||
|
if (c >= 'a' && c <= 'z') {
|
||||||
|
c = static_cast<char>(std::toupper(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(name); // Make sure the variable is not optimized away by compiler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BENCHMARK(loop_lowercase_toupper); // Register the function as a benchmark
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
benchmark::Initialize(&argc, argv);
|
benchmark::Initialize(&argc, argv);
|
||||||
if (benchmark::ReportUnrecognizedArguments(argc, argv)) {
|
if (benchmark::ReportUnrecognizedArguments(argc, argv)) {
|
||||||
|
|
@ -53,16 +75,3 @@ int main(int argc, char** argv) {
|
||||||
benchmark::RunSpecifiedBenchmarks();
|
benchmark::RunSpecifiedBenchmarks();
|
||||||
return EX_OK;
|
return EX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loop_lowercase_toupper(benchmark::State& state) {
|
|
||||||
for (auto _ : state) { // Code inside this loop is measured repeatedly
|
|
||||||
std::string name = data;
|
|
||||||
for (char& c : name) {
|
|
||||||
if (c >= 'a' && c <= 'z') {
|
|
||||||
c = static_cast<char>(std::toupper(c));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
benchmark::DoNotOptimize(name); // Make sure the variable is not optimized away by compiler
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BENCHMARK(loop_lowercase_toupper); // Register the function as a benchmark
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue