mirror of
https://github.com/gunchev/bench.git
synced 2025-11-20 12:15:48 +00:00
Add transform.cpp std::transform test.
This commit is contained in:
parent
8652bbfd99
commit
6811032084
5 changed files with 318 additions and 1 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,3 +1,6 @@
|
|||
# Project specific
|
||||
/build/
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
|
|
|
|||
152
CMakeLists.txt
Normal file
152
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
cmake_minimum_required(VERSION 3.20.0) # RHEL 8
|
||||
|
||||
project(benchmarks
|
||||
VERSION 0.0.0.1 # PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH, and PROJECT_VERSION_TWEAK.
|
||||
DESCRIPTION "Various benchmarks"
|
||||
HOMEPAGE_URL "https://github.com/gunchev/bench/"
|
||||
LANGUAGES C CXX)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED TRUE)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||
|
||||
# set(CMAKE_VERBOSE_MAKEFILE TRUE) # or "cd build; make VERBOSE=1"
|
||||
|
||||
# Build types filter
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING
|
||||
"Choose the type of build, options are: Debug DebugCov RelWithDebInfo Release MinSizeRel." FORCE)
|
||||
endif()
|
||||
|
||||
# SOVERSION is ignored if NO_SONAME property is set.
|
||||
# "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${PROJECT_VERSION_TWEAK}"
|
||||
set(${PROJECT_NAME}_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||
message("${PROJECT_NAME} VERSION ${PROJECT_VERSION} SOVERSION is ${${PROJECT_NAME}_SOVERSION}")
|
||||
|
||||
# Build shared library by default
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
option(BUILD_SHARED_LIBS "Create shared libraries" ON)
|
||||
endif()
|
||||
|
||||
# Add link path(s) to RPATH in shared libraries and executables. Saves setting LD_LIBRARY_PATH each time...
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH 1)
|
||||
|
||||
# Library directory - lib or lib64?
|
||||
# rpm: '%{?_cmake_lib_suffix64}' - https://src.fedoraproject.org/rpms/kid3/blob/rawhide/f/kid3.spec
|
||||
# https://gitlab.kitware.com/cmake/cmake/-/merge_requests/2558
|
||||
if (NOT LIB_SUFFIX)
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(LIB_SUFFIX "")
|
||||
else ()
|
||||
set(LIB_SUFFIX 64)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# -fPIC on all targets
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
|
||||
# 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_CXX_FLAGS "-Wall -Wextra -Werror")
|
||||
endif()
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
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 ON)
|
||||
macro(CheckAndAddFlag flag)
|
||||
# We cannot check for -Wno-foo, check for -Wfoo, see https://stackoverflow.com/a/38786117/1136400 for details.
|
||||
string(REGEX REPLACE "^-Wno-" "-W" checkedFlag ${flag})
|
||||
string(REGEX REPLACE "[^A-Za-z0-9]" "_" varName ${checkedFlag})
|
||||
if(NOT C_CXX${varName}_CHECKED)
|
||||
CHECK_CXX_COMPILER_FLAG(${checkedFlag} CXX_FLAG${varName}_SUPPORTED)
|
||||
CHECK_C_COMPILER_FLAG(${checkedFlag} C_FLAG${varName}_SUPPORTED)
|
||||
set(C_CXX${varName}_CHECKED YES CACHE INTERNAL "")
|
||||
endif()
|
||||
if(CXX_FLAG${varName}_SUPPORTED)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
|
||||
endif()
|
||||
if(C_FLAG${varName}_SUPPORTED)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
|
||||
endif()
|
||||
unset(varName)
|
||||
unset(checkedFlag)
|
||||
endmacro()
|
||||
|
||||
foreach (I IN ITEMS -fmessage-length=0 -fstack-protector-all -pedantic
|
||||
-Weffc++ -Wsign-compare -Wpointer-sign -Wpedantic -Wformat=2 -Wformat-security
|
||||
-Wformat-overflow=2 -Wconversion -Wcast-align -Wcast-qual -Wctor-dtor-privacy
|
||||
-Wdisabled-optimization -Wlogical-op -Wmissing-declarations -Wnoexcept
|
||||
-Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-promo
|
||||
-Wstrict-null-sentinel -Wswitch-default -Wundef -Wfloat-equal -Wstrict-overflow)
|
||||
CheckAndAddFlag(${I})
|
||||
endforeach ()
|
||||
set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_OLD})
|
||||
unset(CMAKE_REQUIRED_QUIET_OLD)
|
||||
|
||||
|
||||
# Linker flags
|
||||
# http://wiki.gentoo.org/wiki/Project:Quality_Assurance/As-needed
|
||||
# http://www.bnikolic.co.uk/blog/gnu-ld-as-needed.html ,--no-undefined,--no-allow-shlib-undefined
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-as-needed")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--no-as-needed")
|
||||
|
||||
# Build target flags
|
||||
# https://fedoraproject.org/wiki/Changes/fno-omit-frame-pointer#Potential_performance_impact
|
||||
# Debug, CMAKE_C_FLAGS is prepended to CMAKE_C_FLAGS_DEBUG and so on, don't duplicate...
|
||||
set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb3 -DDEBUG -fno-inline -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fsanitize=address")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -ggdb3 -DDEBUG -fno-inline -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fsanitize=address")
|
||||
#set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "")
|
||||
#set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "")
|
||||
# Debug with profiling info
|
||||
set(CMAKE_C_FLAGS_DEBUGCOV "-O0 -ggdb3 -DDEBUG -fno-inline -fprofile-arcs -ftest-coverage -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fsanitize=address")
|
||||
set(CMAKE_CXX_FLAGS_DEBUGCOV "-O0 -ggdb3 -DDEBUG -fno-inline -fprofile-arcs -ftest-coverage -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fsanitize=address")
|
||||
# Release with debug info and extra checks, https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#index-fsanitize_003daddress-676
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -ggdb3 -D_FORTIFY_SOURCE=2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -ggdb3 -D_FORTIFY_SOURCE=2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer")
|
||||
# Release
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -ggdb3 -D_FORTIFY_SOURCE=2 -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -ggdb3 -D_FORTIFY_SOURCE=2 -DNDEBUG")
|
||||
# Minimum size release
|
||||
set(CMAKE_C_FLAGS_MINSIZEREL "-Os -ggdb3 -D_FORTIFY_SOURCE=2 -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -ggdb3 -D_FORTIFY_SOURCE=2 -DNDEBUG")
|
||||
|
||||
|
||||
|
||||
# Enable testing?
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(CPPUNIT cppunit>=1.14.0) # REQUIRED
|
||||
if(CPPUNIT_FOUND)
|
||||
enable_testing()
|
||||
include(CTest)
|
||||
find_program(CTEST_COVERAGE_COMMAND NAMES gcov)
|
||||
find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind)
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
endif()
|
||||
|
||||
|
||||
find_package(benchmark REQUIRED)
|
||||
|
||||
# Threads library
|
||||
# set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
# find_package(Threads REQUIRED)
|
||||
|
||||
# Find all third party packages
|
||||
# find_package(fmt REQUIRED)
|
||||
# include_directories(${FMT_INCLUDE_DIR})
|
||||
|
||||
# pkg_check_modules(HIREDIS REQUIRED hiredis>=1.0.2)
|
||||
|
||||
# include_directories(src)
|
||||
|
||||
add_executable(transform src/transform.cpp)
|
||||
target_link_libraries(transform PRIVATE benchmark::benchmark) # fmt::fmt Threads::Threads)
|
||||
install(TARGETS transform DESTINATION bin)
|
||||
105
Makefile
Normal file
105
Makefile
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
TOP := $(shell dirname "$(abspath $(lastword $(MAKEFILE_LIST)))")
|
||||
CMAKE_BUILD_PARALLEL_LEVEL := $(shell (nproc; echo 128) | sort -n | head -n 1)
|
||||
CMAKE := cmake
|
||||
CCMAKE := ccmake
|
||||
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo
|
||||
@echo "| Help"
|
||||
@echo "+======"
|
||||
@echo
|
||||
@echo "Available targets:"
|
||||
@echo " debug: debug build"
|
||||
@echo " debugc: debug build with clang"
|
||||
@echo " debugcov: debug build with coverage"
|
||||
@echo " debugcovc: debug build with coverage with clang"
|
||||
@echo " release: release build"
|
||||
@echo " releasec: release build with clang"
|
||||
@echo " relwithdebinfo: release build with debug info"
|
||||
@echo " relwithdebinfoc: release build with debug info and clang"
|
||||
@echo " minsizerel: minimum size release build (-Os)"
|
||||
@echo " minsizerelc: minimum size release build (-Os) and clang"
|
||||
@echo
|
||||
@echo " distclean: remove all build files"
|
||||
@echo
|
||||
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
( test -d "$(BUILD_DIR)" && cd "$(BUILD_DIR)" && $(MAKE) ) || ( mkdir -p "$(BUILD_DIR)" && cd "$(BUILD_DIR)" && $(CMAKE) -D CMAKE_BUILD_TYPE="$(BUILD_TYPE)" "$(TOP)" && $(MAKE) )
|
||||
|
||||
.PHONY: buildc
|
||||
buildc:
|
||||
( test -d "$(BUILD_DIR)" && cd "$(BUILD_DIR)" && $(MAKE) ) || ( mkdir -p "$(BUILD_DIR)" && cd "$(BUILD_DIR)" && CC=clang CXX=clang++ $(CMAKE) -D CMAKE_BUILD_TYPE="$(BUILD_TYPE)" "$(TOP)" && $(MAKE) )
|
||||
|
||||
.PHONY: debug
|
||||
debug: BUILD_DIR=$(TOP)/build/debug
|
||||
debug: BUILD_TYPE=Debug
|
||||
debug: build
|
||||
|
||||
.PHONY: debugc
|
||||
debugc: BUILD_DIR=$(TOP)/build/debugc
|
||||
debugc: BUILD_TYPE=Debug
|
||||
debugc: buildc
|
||||
|
||||
.PHONY: debugcov
|
||||
debugcov: BUILD_DIR=$(TOP)/build/debugcov
|
||||
debugcov: BUILD_TYPE=DebugCov
|
||||
debugcov: build
|
||||
|
||||
.PHONY: debugcovc
|
||||
debugcovc: BUILD_DIR=$(TOP)/build/debugcovc
|
||||
debugcovc: BUILD_TYPE=DebugCov
|
||||
debugcovc: buildc
|
||||
|
||||
.PHONY: release
|
||||
release: BUILD_DIR=$(TOP)/build/release
|
||||
release: BUILD_TYPE=Release
|
||||
release: build
|
||||
|
||||
.PHONY: releasec
|
||||
releasec: BUILD_DIR=$(TOP)/build/releasec
|
||||
releasec: BUILD_TYPE=Release
|
||||
releasec: buildc
|
||||
|
||||
.PHONY: relwithdebinfo
|
||||
relwithdebinfo: BUILD_DIR=$(TOP)/build/relwithdebinfo
|
||||
relwithdebinfo: BUILD_TYPE=RelWithDebInfo
|
||||
relwithdebinfo: build
|
||||
|
||||
.PHONY: relwithdebinfoc
|
||||
relwithdebinfoc: BUILD_DIR=$(TOP)/build/relwithdebinfoc
|
||||
relwithdebinfoc: BUILD_TYPE=RelWithDebInfo
|
||||
relwithdebinfoc: buildc
|
||||
|
||||
.PHONY: minsizerel
|
||||
minsizerel: BUILD_DIR=$(TOP)/build/minsizerel
|
||||
minsizerel: BUILD_TYPE=MinSizeRel
|
||||
minsizerel: build
|
||||
|
||||
.PHONY: minsizerelc
|
||||
minsizerelc: BUILD_DIR=$(TOP)/build/minsizerelc
|
||||
minsizerelc: BUILD_TYPE=MinSizeRel
|
||||
minsizerelc: buildc
|
||||
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
make debug
|
||||
make debugcov
|
||||
make release
|
||||
make relwithdebinfo
|
||||
make minsizerel
|
||||
make debugc
|
||||
make debugcovc
|
||||
make releasec
|
||||
make relwithdebinfoc
|
||||
make minsizerelc
|
||||
|
||||
|
||||
distclean:
|
||||
-rm -rf "$(TOP)"/build/
|
||||
.PHONY: distclean
|
||||
dc: distclean
|
||||
|
|
@ -1,2 +1,4 @@
|
|||
# bench
|
||||
Various C++ benchmarks
|
||||
Various C++ benchmarks:
|
||||
|
||||
- transform.cpp - benchmark std::transform vs loop and custom lowercase and tolower
|
||||
|
|
|
|||
55
src/transform.cpp
Executable file
55
src/transform.cpp
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
/*/true;A="$(readlink -f -- "$0")";g++ --std=c++20 -O3 -Wall -Wextra -lbenchmark -o "$A.bin" "$A"&&"$A.bin" "$@";E=$?;rm "$A.bin";exit $E #*/
|
||||
#include <algorithm>
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <string>
|
||||
#include <sysexits.h>
|
||||
|
||||
|
||||
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) {
|
||||
for (auto _ : state) { // Code inside this loop is measured repeatedly
|
||||
std::string name = data;
|
||||
std::transform(name.cbegin(), name.cend(), name.begin(), [](char c) noexcept {
|
||||
return (c >= 'a' && c <= 'z') ? c = c - 'a' + 'A' : c;
|
||||
});
|
||||
benchmark::DoNotOptimize(name); // Make sure the variable is not optimized away by compiler
|
||||
}
|
||||
}
|
||||
BENCHMARK(algorithm_lowercase_my); // Register the function as a benchmark
|
||||
|
||||
static void loop_lowercase_my(benchmark::State& state) {
|
||||
for (auto _ : state) { // Code before the loop is not measured
|
||||
std::string name = data;
|
||||
for (char& c : name) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
c = c - 'a' + 'A';
|
||||
}
|
||||
}
|
||||
benchmark::DoNotOptimize(name); // Make sure the variable is not optimized away by compiler
|
||||
}
|
||||
}
|
||||
BENCHMARK(loop_lowercase_my); // Register the function as a benchmark
|
||||
|
||||
|
||||
static void algorithm_lowercase_toupper(benchmark::State& state) {
|
||||
for (auto _ : state) { // Code inside this loop is measured repeatedly
|
||||
std::string name = data;
|
||||
std::transform(name.cbegin(), name.cend(), name.begin(), [](char c) noexcept {
|
||||
return std::toupper(static_cast<unsigned char>(c));
|
||||
});
|
||||
benchmark::DoNotOptimize(name); // Make sure the variable is not optimized away by compiler
|
||||
}
|
||||
}
|
||||
BENCHMARK(algorithm_lowercase_toupper); // Register the function as a benchmark
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv)) {
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
return EX_OK;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue