Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add benchmarks #169

Merged
merged 11 commits into from
Oct 8, 2024
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
6 changes: 5 additions & 1 deletion .github/workflows/bvt-appleclang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ jobs:

- name: build and run test with AppleClang
run: |
cmake -B build
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
ctest --test-dir build -j

- name: run benchmarks
run: |
./build/benchmarks/msft_proxy_benchmarks --benchmark_repetitions=10 --benchmark_report_aggregates_only=true
12 changes: 8 additions & 4 deletions .github/workflows/bvt-clang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,28 @@ jobs:

- name: build and run test with clang 15
run: |
cmake -B build-clang-15 -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15
cmake -B build-clang-15 -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -DCMAKE_BUILD_TYPE=Release
cmake --build build-clang-15 -j
ctest --test-dir build-clang-15 -j

- name: build and run test with clang 16
run: |
cmake -B build-clang-16 -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16
cmake -B build-clang-16 -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_BUILD_TYPE=Release
cmake --build build-clang-16 -j
ctest --test-dir build-clang-16 -j

- name: build and run test with clang 17
run: |
cmake -B build-clang-17 -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17
cmake -B build-clang-17 -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_BUILD_TYPE=Release
cmake --build build-clang-17 -j
ctest --test-dir build-clang-17 -j

- name: build and run test with clang 18
run: |
cmake -B build-clang-18 -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18
cmake -B build-clang-18 -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_BUILD_TYPE=Release
cmake --build build-clang-18 -j
ctest --test-dir build-clang-18 -j

- name: run benchmarks
run: |
./build-clang-18/benchmarks/msft_proxy_benchmarks --benchmark_repetitions=10 --benchmark_report_aggregates_only=true
12 changes: 8 additions & 4 deletions .github/workflows/bvt-gcc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,28 @@ jobs:

- name: build and run test with gcc 11
run: |
cmake -B build-gcc-11 -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11
cmake -B build-gcc-11 -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Release
cmake --build build-gcc-11 -j
ctest --test-dir build-gcc-11 -j

- name: build and run test with gcc 12
run: |
cmake -B build-gcc-12 -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12
cmake -B build-gcc-12 -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_BUILD_TYPE=Release
cmake --build build-gcc-12 -j
ctest --test-dir build-gcc-12 -j

- name: build and run test with gcc 13
run: |
cmake -B build-gcc-13 -DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13
cmake -B build-gcc-13 -DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13 -DCMAKE_BUILD_TYPE=Release
cmake --build build-gcc-13 -j
ctest --test-dir build-gcc-13 -j

- name: build and run test with gcc 14
run: |
cmake -B build-gcc-14 -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14
cmake -B build-gcc-14 -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_BUILD_TYPE=Release
cmake --build build-gcc-14 -j
ctest --test-dir build-gcc-14 -j

- name: run benchmarks
run: |
./build-gcc-14/benchmarks/msft_proxy_benchmarks --benchmark_repetitions=10 --benchmark_report_aggregates_only=true
9 changes: 5 additions & 4 deletions .github/workflows/bvt-msvc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ jobs:
with:
ref: ${{ inputs.branch }}

- name: build with cmake
- name: build and run test with MSVC
run: |
cmake -B build
cmake --build build -j
cmake --build build --config Release -j
ctest --test-dir build -j

- name: run tests
- name: run benchmarks
run: |
ctest --test-dir build -j
.\build\benchmarks\Release\msft_proxy_benchmarks.exe --benchmark_repetitions=10 --benchmark_report_aggregates_only=true
16 changes: 1 addition & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,7 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/proxyConfigVersion.cmake
# build tests if BUILD_TESTING is ON
include(CTest)
if (BUILD_TESTING)
include(FetchContent)
# The policy uses the download time for timestamp, instead of the timestamp in the archive. This
# allows for proper rebuilds when a projects URL changes.
if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/releases/download/v1.15.2/googletest-1.15.2.tar.gz
)

set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # For Windows: Prevent overriding the parent project's compiler/linker settings
set(BUILD_GMOCK OFF CACHE BOOL "" FORCE) # Disable GMock
FetchContent_MakeAvailable(googletest)

add_subdirectory(tests)
add_subdirectory(benchmarks)
add_subdirectory(samples)
endif()
31 changes: 31 additions & 0 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
project(msft_proxy_benchmarks)

include(FetchContent)
# The policy uses the download time for timestamp, instead of the timestamp in the archive. This
# allows for proper rebuilds when a projects URL changes.
if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()

FetchContent_Declare(
benchmark
URL https://github.com/google/benchmark/archive/refs/tags/v1.9.0.tar.gz
URL_HASH SHA256=35a77f46cc782b16fac8d3b107fbfbb37dcd645f7c28eee19f3b8e0758b48994
)
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Disable tests for google benchmark")
set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "Disable google benchmark unit tests")
FetchContent_MakeAvailable(benchmark)

add_executable(msft_proxy_benchmarks
proxy_invocation_benchmark_context.cpp
proxy_invocation_benchmark.cpp
proxy_management_benchmark.cpp
)
target_include_directories(msft_proxy_benchmarks PRIVATE .)
target_link_libraries(msft_proxy_benchmarks PRIVATE msft_proxy benchmark::benchmark benchmark::benchmark_main)

if (MSVC)
target_compile_options(msft_proxy_benchmarks PRIVATE /W4)
else()
target_compile_options(msft_proxy_benchmarks PRIVATE -Wall -Wextra -Wpedantic)
endif()
47 changes: 47 additions & 0 deletions benchmarks/proxy_invocation_benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#include <benchmark/benchmark.h>

#include "proxy_invocation_benchmark_context.h"

void BM_SmallObjectInvocationViaProxy(benchmark::State& state) {
for (auto _ : state) {
for (auto& p : SmallObjectInvocationProxyTestData) {
int result = p->Fun();
benchmark::DoNotOptimize(result);
}
}
}

void BM_SmallObjectInvocationViaVirtualFunction(benchmark::State& state) {
for (auto _ : state) {
for (auto& p : SmallObjectInvocationVirtualFunctionTestData) {
int result = p->Fun();
benchmark::DoNotOptimize(result);
}
}
}

void BM_LargeObjectInvocationViaProxy(benchmark::State& state) {
for (auto _ : state) {
for (auto& p : LargeObjectInvocationProxyTestData) {
int result = p->Fun();
benchmark::DoNotOptimize(result);
}
}
}

void BM_LargeObjectInvocationViaVirtualFunction(benchmark::State& state) {
for (auto _ : state) {
for (auto& p : LargeObjectInvocationVirtualFunctionTestData) {
int result = p->Fun();
benchmark::DoNotOptimize(result);
}
}
}

BENCHMARK(BM_SmallObjectInvocationViaProxy);
BENCHMARK(BM_SmallObjectInvocationViaVirtualFunction);
BENCHMARK(BM_LargeObjectInvocationViaProxy);
BENCHMARK(BM_LargeObjectInvocationViaVirtualFunction);
93 changes: 93 additions & 0 deletions benchmarks/proxy_invocation_benchmark_context.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#include "proxy_invocation_benchmark_context.h"

namespace {

constexpr int TestDataSize = 1000000;
constexpr int TypeSeriesCount = 100;

template <int TypeSeries>
class NonIntrusiveSmallImpl {
public:
explicit NonIntrusiveSmallImpl(int seed) noexcept : seed_(seed) {}
NonIntrusiveSmallImpl(const NonIntrusiveSmallImpl&) noexcept = default;
int Fun() const noexcept { return seed_ ^ (TypeSeries + 1); }

private:
int seed_;
};

template <int TypeSeries>
class NonIntrusiveLargeImpl {
public:
explicit NonIntrusiveLargeImpl(int seed) noexcept : seed_(seed) {}
NonIntrusiveLargeImpl(const NonIntrusiveLargeImpl&) noexcept = default;
int Fun() const noexcept { return seed_ ^ (TypeSeries + 1); }

private:
void* padding_[15]{};
int seed_;
};

template <int TypeSeries>
class IntrusiveSmallImpl : public InvocationTestBase {
public:
explicit IntrusiveSmallImpl(int seed) noexcept : seed_(seed) {}
IntrusiveSmallImpl(const IntrusiveSmallImpl&) noexcept = default;
int Fun() const noexcept override { return seed_ ^ (TypeSeries + 1); }

private:
int seed_;
};

template <int TypeSeries>
class IntrusiveLargeImpl : public InvocationTestBase {
public:
explicit IntrusiveLargeImpl(int seed) noexcept : seed_(seed) {}
IntrusiveLargeImpl(const IntrusiveLargeImpl&) noexcept = default;
int Fun() const noexcept override { return seed_ ^ (TypeSeries + 1); }

private:
void* padding_[16]{};
int seed_;
};

template <int V>
struct IntConstant {};

template <int FromTypeSeries, class T, class F>
void FillTestData(std::vector<T>& data, const F& generator) {
if constexpr (FromTypeSeries < TypeSeriesCount) {
for (int i = FromTypeSeries; i < TestDataSize; i += TypeSeriesCount) {
data[i] = generator(IntConstant<FromTypeSeries>{}, i);
}
FillTestData<FromTypeSeries + 1>(data, generator);
}
}

template <class F>
auto GenerateTestData(const F& generator) {
std::vector<decltype(generator(IntConstant<0>{}, 0))> result(TestDataSize);
FillTestData<0>(result, generator);
return result;
}

} // namespace

const std::vector<pro::proxy<InvocationTestFacade>> SmallObjectInvocationProxyTestData = GenerateTestData(
[]<int TypeSeries>(IntConstant<TypeSeries>, int seed)
{ return pro::make_proxy<InvocationTestFacade, NonIntrusiveSmallImpl<TypeSeries>>(seed); });

const std::vector<std::unique_ptr<InvocationTestBase>> SmallObjectInvocationVirtualFunctionTestData = GenerateTestData(
[]<int TypeSeries>(IntConstant<TypeSeries>, int seed)
{ return std::unique_ptr<InvocationTestBase>{new IntrusiveSmallImpl<TypeSeries>(seed)}; });

const std::vector<pro::proxy<InvocationTestFacade>> LargeObjectInvocationProxyTestData = GenerateTestData(
[]<int TypeSeries>(IntConstant<TypeSeries>, int seed)
{ return pro::make_proxy<InvocationTestFacade, NonIntrusiveLargeImpl<TypeSeries>>(seed); });

const std::vector<std::unique_ptr<InvocationTestBase>> LargeObjectInvocationVirtualFunctionTestData = GenerateTestData(
[]<int TypeSeries>(IntConstant<TypeSeries>, int seed)
{ return std::unique_ptr<InvocationTestBase>{new IntrusiveLargeImpl<TypeSeries>(seed)}; });
23 changes: 23 additions & 0 deletions benchmarks/proxy_invocation_benchmark_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#include <memory>
#include <vector>

#include "proxy.h"

PRO_DEF_MEM_DISPATCH(MemFun, Fun);

struct InvocationTestFacade : pro::facade_builder
::add_convention<MemFun, int() const>
::build{};

struct InvocationTestBase {
virtual int Fun() const = 0;
virtual ~InvocationTestBase() = default;
};

extern const std::vector<pro::proxy<InvocationTestFacade>> SmallObjectInvocationProxyTestData;
extern const std::vector<std::unique_ptr<InvocationTestBase>> SmallObjectInvocationVirtualFunctionTestData;
extern const std::vector<pro::proxy<InvocationTestFacade>> LargeObjectInvocationProxyTestData;
extern const std::vector<std::unique_ptr<InvocationTestBase>> LargeObjectInvocationVirtualFunctionTestData;
Loading
Loading