diff --git a/smoke/CMakeLists.txt b/smoke/CMakeLists.txt index ca1cc03..50833bc 100644 --- a/smoke/CMakeLists.txt +++ b/smoke/CMakeLists.txt @@ -5,6 +5,7 @@ project(protocyte_smoke LANGUAGES CXX) option(PROTOCYTE_SMOKE_REGENERATE "Regenerate checked protocyte output with protoc." OFF) option(PROTOCYTE_SMOKE_FETCH_PROTOBUF "Fetch and build protobuf when protoc is not installed." ON) option(PROTOCYTE_SMOKE_BUILD_DRIVER "Build the WDK kernel driver smoke test." OFF) +option(PROTOCYTE_SMOKE_BUILD_BENCHMARKS "Build Protocyte marshalling benchmarks." OFF) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -17,6 +18,7 @@ set(PROTOCYTE_SMOKE_PROTO_DIR "${CMAKE_CURRENT_LIST_DIR}/proto") set(PROTOCYTE_EXAMPLE_PROTO "${PROTOCYTE_SMOKE_PROTO_DIR}/example.proto") set(PROTOCYTE_COMPAT_PROTO "${PROTOCYTE_SMOKE_PROTO_DIR}/compat.proto") set(PROTOCYTE_CROSS_PACKAGE_PROTO "${PROTOCYTE_SMOKE_PROTO_DIR}/cross_package.proto") +set(PROTOCYTE_BENCHMARK_PROTO "${PROTOCYTE_SMOKE_PROTO_DIR}/benchmark.proto") set(PROTOCYTE_GENERATED_DIR "${CMAKE_CURRENT_LIST_DIR}/generated") set( PROTOCYTE_SMOKE_CLANG_FORMAT @@ -40,7 +42,7 @@ set(PROTOCYTE_GENERATED_FILES "${PROTOCYTE_GENERATED_DIR}/protocyte/runtime/runtime.hpp" ) -if(PROTOCYTE_SMOKE_REGENERATE) +if(PROTOCYTE_SMOKE_REGENERATE OR PROTOCYTE_SMOKE_BUILD_BENCHMARKS) set(PROTOCYTE_FETCH_PROTOBUF "${PROTOCYTE_SMOKE_FETCH_PROTOBUF}") else() set(PROTOCYTE_FETCH_PROTOBUF OFF) @@ -115,6 +117,87 @@ FetchContent_Declare( GIT_TAG v3.7.1 ) FetchContent_MakeAvailable(Catch2) +FetchContent_GetProperties(Catch2 SOURCE_DIR protocyte_smoke_catch2_source_dir) +list(APPEND CMAKE_MODULE_PATH "${protocyte_smoke_catch2_source_dir}/extras") + +if(PROTOCYTE_SMOKE_BUILD_BENCHMARKS) + set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE) + set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE) + set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) + set(BENCHMARK_INSTALL_DOCS OFF CACHE BOOL "" FORCE) + set(BENCHMARK_INSTALL_TOOLS OFF CACHE BOOL "" FORCE) + if(WIN32) + set(CMAKE_USE_WIN32_THREADS_INIT ON CACHE BOOL "" FORCE) + set(CMAKE_USE_PTHREADS_INIT OFF CACHE BOOL "" FORCE) + set(CMAKE_THREAD_LIBS_INIT "" CACHE STRING "" FORCE) + set(HAVE_LIB_RT OFF CACHE BOOL "" FORCE) + endif() + FetchContent_Declare( + benchmark + GIT_REPOSITORY https://github.com/google/benchmark.git + GIT_TAG v1.9.5 + ) + FetchContent_MakeAvailable(benchmark) + + set(protobuf_MSVC_STATIC_RUNTIME OFF CACHE BOOL "" FORCE) + protocyte_setup_codegen() + if(NOT TARGET protobuf::libprotobuf AND NOT TARGET libprotobuf) + find_package(Protobuf CONFIG QUIET) + endif() + if(NOT TARGET protobuf::libprotobuf AND NOT TARGET libprotobuf) + find_package(Protobuf MODULE QUIET) + endif() + if(NOT TARGET protobuf::libprotobuf AND NOT TARGET libprotobuf AND PROTOCYTE_SMOKE_FETCH_PROTOBUF) + set(protobuf_BUILD_TESTS OFF CACHE BOOL "" FORCE) + set(protobuf_BUILD_CONFORMANCE OFF CACHE BOOL "" FORCE) + set(protobuf_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) + set(protobuf_BUILD_PROTOBUF_BINARIES ON CACHE BOOL "" FORCE) + FetchContent_Declare( + protobuf + GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git + GIT_TAG "${PROTOCYTE_PROTOBUF_GIT_TAG}" + ) + FetchContent_MakeAvailable(protobuf) + set(PROTOCYTE_PROTOC_EXECUTABLE "$" CACHE INTERNAL "protoc executable for protocyte") + endif() + set(PROTOCYTE_PROTOBUF_BENCHMARK_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated/protobuf") + set(PROTOCYTE_PROTOBUF_BENCHMARK_HEADER "${PROTOCYTE_PROTOBUF_BENCHMARK_GENERATED_DIR}/benchmark.pb.h") + set(PROTOCYTE_PROTOBUF_BENCHMARK_SOURCE "${PROTOCYTE_PROTOBUF_BENCHMARK_GENERATED_DIR}/benchmark.pb.cc") + add_custom_command( + OUTPUT + "${PROTOCYTE_PROTOBUF_BENCHMARK_HEADER}" + "${PROTOCYTE_PROTOBUF_BENCHMARK_SOURCE}" + COMMAND + "${CMAKE_COMMAND}" -E make_directory "${PROTOCYTE_PROTOBUF_BENCHMARK_GENERATED_DIR}" + COMMAND + ${PROTOCYTE_PROTOC_EXECUTABLE} + "--proto_path=${PROTOCYTE_SMOKE_PROTO_DIR}" + "--cpp_out=${PROTOCYTE_PROTOBUF_BENCHMARK_GENERATED_DIR}" + "${PROTOCYTE_BENCHMARK_PROTO}" + DEPENDS "${PROTOCYTE_BENCHMARK_PROTO}" + COMMENT "Generating protobuf benchmark C++ sources" + VERBATIM + ) + add_custom_target( + protocyte_smoke_protobuf_benchmark_codegen + DEPENDS + "${PROTOCYTE_PROTOBUF_BENCHMARK_HEADER}" + "${PROTOCYTE_PROTOBUF_BENCHMARK_SOURCE}" + ) + set_source_files_properties( + "${PROTOCYTE_PROTOBUF_BENCHMARK_SOURCE}" + PROPERTIES + COMPILE_OPTIONS "$<$:-Wno-invalid-offsetof>" + ) + + if(TARGET protobuf::libprotobuf) + set(protocyte_smoke_libprotobuf_target protobuf::libprotobuf) + elseif(TARGET libprotobuf) + set(protocyte_smoke_libprotobuf_target libprotobuf) + else() + message(FATAL_ERROR "protobuf benchmark requires a libprotobuf CMake target") + endif() +endif() add_executable(protocyte_host_smoke src/host_smoke.cpp @@ -142,6 +225,69 @@ else() target_compile_options(protocyte_host_smoke PRIVATE -Wall -Wextra -Wpedantic) endif() +if(PROTOCYTE_SMOKE_BUILD_BENCHMARKS) + add_executable(protocyte_host_benchmark + src/host_benchmark.cpp + "${PROTOCYTE_GENERATED_DIR}/example.protocyte.cpp" + "${PROTOCYTE_GENERATED_DIR}/compat.protocyte.cpp" + "${PROTOCYTE_GENERATED_DIR}/cross_package.protocyte.cpp" + ) + target_include_directories(protocyte_host_benchmark PRIVATE "${PROTOCYTE_GENERATED_DIR}") + target_compile_definitions( + protocyte_host_benchmark + PRIVATE + PROTOCYTE_ENABLE_HOSTED_ALLOCATOR=1 + PROTOCYTE_ENABLE_STD_STRING_VIEW=1 + ) + target_compile_features(protocyte_host_benchmark PRIVATE cxx_std_20) + target_link_libraries(protocyte_host_benchmark PRIVATE benchmark::benchmark_main) + + if(PROTOCYTE_SMOKE_REGENERATE) + add_dependencies(protocyte_host_benchmark protocyte_smoke_regenerate) + endif() + + if(MSVC) + target_compile_options(protocyte_host_benchmark PRIVATE /W4 /permissive-) + else() + target_compile_options(protocyte_host_benchmark PRIVATE -Wall -Wextra -Wpedantic) + endif() + + add_executable(protocyte_host_protobuf_benchmark + src/protobuf_benchmark.cpp + "${PROTOCYTE_PROTOBUF_BENCHMARK_SOURCE}" + ) + target_include_directories( + protocyte_host_protobuf_benchmark + PRIVATE + "${PROTOCYTE_GENERATED_DIR}" + "${PROTOCYTE_PROTOBUF_BENCHMARK_GENERATED_DIR}" + ) + target_compile_definitions( + protocyte_host_protobuf_benchmark + PRIVATE + PROTOCYTE_ENABLE_HOSTED_ALLOCATOR=1 + PROTOCYTE_ENABLE_STD_STRING_VIEW=1 + ) + target_compile_features(protocyte_host_protobuf_benchmark PRIVATE cxx_std_20) + target_link_libraries( + protocyte_host_protobuf_benchmark + PRIVATE + benchmark::benchmark_main + "${protocyte_smoke_libprotobuf_target}" + ) + add_dependencies(protocyte_host_protobuf_benchmark protocyte_smoke_protobuf_benchmark_codegen) + + if(PROTOCYTE_SMOKE_REGENERATE) + add_dependencies(protocyte_host_protobuf_benchmark protocyte_smoke_regenerate) + endif() + + if(MSVC) + target_compile_options(protocyte_host_protobuf_benchmark PRIVATE /W4 /permissive-) + else() + target_compile_options(protocyte_host_protobuf_benchmark PRIVATE -Wall -Wextra -Wpedantic) + endif() +endif() + enable_testing() include(Catch) catch_discover_tests(protocyte_host_smoke) diff --git a/smoke/CMakePresets.json b/smoke/CMakePresets.json index b87d52d..92675b6 100644 --- a/smoke/CMakePresets.json +++ b/smoke/CMakePresets.json @@ -9,6 +9,7 @@ "PATH": "$env{VCINSTALLDIR}Tools/Llvm/x64/bin;$env{VSINSTALLDIR}Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja;$env{WindowsSdkVerBinPath}x64;$penv{PATH}" }, "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", "CMAKE_CXX_COMPILER": "clang-cl", "CMAKE_RC_COMPILER": "rc", "CMAKE_TRY_COMPILE_TARGET_TYPE": "STATIC_LIBRARY" @@ -22,6 +23,7 @@ "PATH": "$env{VSINSTALLDIR}Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja;$env{WindowsSdkVerBinPath}x64;$penv{PATH}" }, "cacheVariables": { + "CMAKE_C_COMPILER": "cl", "CMAKE_CXX_COMPILER": "cl", "CMAKE_RC_COMPILER": "rc", "CMAKE_TRY_COMPILE_TARGET_TYPE": "STATIC_LIBRARY" @@ -39,6 +41,24 @@ "displayName": "Windows MSVC + Ninja", "binaryDir": "${sourceDir}/build/msvc" }, + { + "name": "windows-clangcl-ninja-benchmarks", + "inherits": "windows-clangcl-ninja", + "displayName": "Windows clang-cl + Ninja + benchmarks", + "binaryDir": "${sourceDir}/build/clangcl-benchmarks", + "cacheVariables": { + "PROTOCYTE_SMOKE_BUILD_BENCHMARKS": "ON" + } + }, + { + "name": "windows-msvc-ninja-benchmarks", + "inherits": "windows-msvc-ninja", + "displayName": "Windows MSVC + Ninja + benchmarks", + "binaryDir": "${sourceDir}/build/msvc-benchmarks", + "cacheVariables": { + "PROTOCYTE_SMOKE_BUILD_BENCHMARKS": "ON" + } + }, { "name": "windows-clangcl-ninja-driver", "inherits": "windows-clangcl-ninja", @@ -67,6 +87,14 @@ "name": "windows-msvc-ninja", "configurePreset": "windows-msvc-ninja" }, + { + "name": "windows-clangcl-ninja-benchmarks", + "configurePreset": "windows-clangcl-ninja-benchmarks" + }, + { + "name": "windows-msvc-ninja-benchmarks", + "configurePreset": "windows-msvc-ninja-benchmarks" + }, { "name": "windows-clangcl-ninja-driver", "configurePreset": "windows-clangcl-ninja-driver" diff --git a/smoke/proto/benchmark.proto b/smoke/proto/benchmark.proto new file mode 100644 index 0000000..77289e1 --- /dev/null +++ b/smoke/proto/benchmark.proto @@ -0,0 +1,125 @@ +syntax = "proto3"; + +package test.benchmark; + +message BenchmarkMessage { + double f_double = 1; + float f_float = 2; + int32 f_int32 = 4; + int64 f_int64 = 8; + uint32 f_uint32 = 9; + uint64 f_uint64 = 10; + sint32 f_sint32 = 11; + sint64 f_sint64 = 12; + fixed32 f_fixed32 = 13; + fixed64 f_fixed64 = 14; + sfixed32 f_sfixed32 = 15; + sfixed64 f_sfixed64 = 16; + bool f_bool = 17; + string f_string = 18; + bytes f_bytes = 19; + + repeated int32 r_int32_unpacked = 21 [packed = false]; + repeated int32 r_int32_packed = 22 [packed = true]; + repeated double r_double = 23; + + enum Color { + COLOR_UNSPECIFIED = 0; + RED = 1; + GREEN = 2; + BLUE = 3; + } + + Color color = 24; + + message NestedLevel1 { + string name = 1; + int32 id = 2; + + message NestedLevel2 { + string description = 1; + repeated float values = 2; + + enum InnerEnum { + INNER_UNSPECIFIED = 0; + A = 1; + B = 2; + C = 3; + } + + InnerEnum mode = 3; + } + + NestedLevel2 inner = 3; + } + + NestedLevel1 nested1 = 25; + + oneof special_oneof { + string oneof_string = 26; + int32 oneof_int32 = 27; + NestedLevel1 oneof_msg = 28; + bytes oneof_bytes = 29; + } + + message RepeatedBytesHolder { + repeated bytes values = 1; + } + + message BoundedRepeatedBytesHolder { + repeated bytes values = 1; + } + + message FixedRepeatedBytesHolder { + repeated bytes values = 1; + } + + oneof crazy_bytes_oneof { + bytes crazy_plain_bytes = 49; + bytes crazy_bounded_bytes = 50; + bytes crazy_fixed_bytes = 51; + RepeatedBytesHolder crazy_repeated_bytes = 52; + BoundedRepeatedBytesHolder crazy_bounded_repeated_bytes = 53; + FixedRepeatedBytesHolder crazy_fixed_repeated_bytes = 54; + } + + map map_str_int32 = 30; + map map_int32_str = 31; + map map_bool_bytes = 32; + map map_uint64_msg = 33; + map very_nested_map = 34; + + BenchmarkMessage recursive_self = 35; + repeated NestedLevel1.NestedLevel2 lots_of_nested = 36; + repeated Color colors = 37; + optional int32 opt_int32 = 38; + optional string opt_string = 39; + + message LevelA { + message LevelB { + message LevelC { + message LevelD { + message LevelE { + string extreme = 1; + map weird_map = 2; + oneof deep_oneof { + int64 val = 3; + string text = 4; + } + } + } + } + } + } + + LevelA.LevelB.LevelC.LevelD.LevelE extreme_nesting = 40; + + bytes sha256 = 41; + repeated int32 integer_array = 42; + bytes byte_array = 43; + repeated uint32 fixed_integer_array = 44; + bytes float_expr_array = 45; + repeated bytes repeated_byte_array = 46; + repeated bytes bounded_repeated_byte_array = 47; + repeated bytes fixed_repeated_byte_array = 48; +} diff --git a/smoke/src/host_benchmark.cpp b/smoke/src/host_benchmark.cpp new file mode 100644 index 0000000..fa70363 --- /dev/null +++ b/smoke/src/host_benchmark.cpp @@ -0,0 +1,115 @@ +#include + +#include +#include + +#include "host_fixture.hpp" + +namespace { + + using Fixture = protocyte_smoke::fixture::Message; + + bool make_populated_message(Fixture &message, protocyte_smoke::fixture::Config::Context &ctx, + benchmark::State &state) { + if (const auto st = protocyte_smoke::fixture::populate_message(message, ctx); !st) { + state.SkipWithError("populate_message failed"); + return false; + } + return true; + } + + bool make_encoded_message(std::vector &encoded, benchmark::State &state) { + auto ctx = protocyte_smoke::fixture::make_context(); + Fixture message(ctx); + if (!make_populated_message(message, ctx, state)) { + return false; + } + + const auto encoded_size = message.encoded_size(); + if (!encoded_size) { + state.SkipWithError("encoded_size failed"); + return false; + } + + encoded.resize(*encoded_size); + protocyte::SliceWriter writer(encoded.data(), encoded.size()); + if (const auto st = message.serialize(writer); !st) { + state.SkipWithError("serialize failed"); + return false; + } + if (writer.position() != encoded.size()) { + state.SkipWithError("serialize wrote an unexpected number of bytes"); + return false; + } + return true; + } + + void BM_UltimateComplexMessage_EncodedSize(benchmark::State &state) { + auto ctx = protocyte_smoke::fixture::make_context(); + Fixture message(ctx); + if (!make_populated_message(message, ctx, state)) { + return; + } + + for (auto _ : state) { + const auto encoded_size = message.encoded_size(); + if (!encoded_size) { + state.SkipWithError("encoded_size failed"); + break; + } + auto size_value = *encoded_size; + benchmark::DoNotOptimize(size_value); + } + } + + void BM_UltimateComplexMessage_Serialize(benchmark::State &state) { + auto ctx = protocyte_smoke::fixture::make_context(); + Fixture message(ctx); + if (!make_populated_message(message, ctx, state)) { + return; + } + + const auto encoded_size = message.encoded_size(); + if (!encoded_size) { + state.SkipWithError("encoded_size failed"); + return; + } + std::vector buffer(*encoded_size); + + for (auto _ : state) { + protocyte::SliceWriter writer(buffer.data(), buffer.size()); + if (const auto st = message.serialize(writer); !st) { + state.SkipWithError("serialize failed"); + break; + } + benchmark::DoNotOptimize(writer.position()); + benchmark::ClobberMemory(); + } + state.SetBytesProcessed(static_cast(state.iterations()) * static_cast(buffer.size())); + } + + void BM_UltimateComplexMessage_MergeFrom(benchmark::State &state) { + std::vector encoded; + if (!make_encoded_message(encoded, state)) { + return; + } + + for (auto _ : state) { + auto ctx = protocyte_smoke::fixture::make_context(); + Fixture parsed(ctx); + protocyte::SliceReader reader(encoded.data(), encoded.size()); + if (const auto st = parsed.merge_from(reader); !st) { + state.SkipWithError("merge_from failed"); + break; + } + benchmark::DoNotOptimize(parsed.f_int32()); + benchmark::ClobberMemory(); + } + state.SetBytesProcessed(static_cast(state.iterations()) * static_cast(encoded.size())); + } + + BENCHMARK(BM_UltimateComplexMessage_EncodedSize); + BENCHMARK(BM_UltimateComplexMessage_Serialize); + BENCHMARK(BM_UltimateComplexMessage_MergeFrom); + +} // namespace diff --git a/smoke/src/host_fixture.hpp b/smoke/src/host_fixture.hpp new file mode 100644 index 0000000..7e27c31 --- /dev/null +++ b/smoke/src/host_fixture.hpp @@ -0,0 +1,423 @@ +#pragma once + +#include +#include +#include +#include + +#include "example.protocyte.hpp" +#include "protocyte/runtime/runtime.hpp" + +namespace protocyte_smoke::fixture { + + using Config = protocyte::DefaultConfig; + using Message = ::test::ultimate::UltimateComplexMessage<>; + using Nested1 = ::test::ultimate::UltimateComplexMessage_NestedLevel1<>; + using Nested2 = ::test::ultimate::UltimateComplexMessage_NestedLevel1_NestedLevel2<>; + using RepeatedBytesHolder = ::test::ultimate::UltimateComplexMessage_RepeatedBytesHolder<>; + using BoundedRepeatedBytesHolder = ::test::ultimate::UltimateComplexMessage_BoundedRepeatedBytesHolder<>; + using FixedRepeatedBytesHolder = ::test::ultimate::UltimateComplexMessage_FixedRepeatedBytesHolder<>; + using Deep = ::test::ultimate::UltimateComplexMessage_LevelA_LevelB_LevelC_LevelD_LevelE<>; + using Color = ::test::ultimate::UltimateComplexMessage_Color; + using InnerMode = ::test::ultimate::UltimateComplexMessage_NestedLevel1_NestedLevel2_InnerEnum; + + constexpr uint8_t string_bytes[] = {'s', 'm', 'o', 'k', 'e'}; + constexpr uint8_t bytes_data[] = {0x00u, 0x01u, 0x7fu, 0x80u, 0xffu}; + constexpr uint8_t nested_name[] = {'n', 'e', 's', 't', 'e', 'd'}; + constexpr uint8_t nested_description[] = {'i', 'n', 'n', 'e', 'r'}; + constexpr uint8_t oneof_bytes[] = {0xdeu, 0xadu, 0xbeu, 0xefu}; + constexpr uint8_t map_key[] = {'m', 'a', 'p', '-', 'k', 'e', 'y'}; + constexpr uint8_t map_value[] = {'m', 'a', 'p', '-', 'v', 'a', 'l'}; + constexpr uint8_t bool_bytes[] = {'b', 'o', 'o', 'l'}; + constexpr uint8_t very_nested_key[] = {'v', 'e', 'r', 'y'}; + constexpr uint8_t recursive_string[] = {'r', 'e', 'c'}; + constexpr uint8_t optional_string[] = {'o', 'p', 't'}; + constexpr uint8_t extreme_value[] = {'e', 'x', 't', 'r', 'e', 'm', 'e'}; + constexpr uint8_t deep_text[] = {'d', 'e', 'e', 'p'}; + constexpr uint8_t weird_value[] = {'w', 'e', 'i', 'r', 'd'}; + constexpr uint8_t byte_array[] = {0xa1u, 0xb2u, 0xc3u, 0xd4u}; + constexpr uint8_t float_expr_array[] = {0x91u, 0x92u}; + constexpr uint8_t repeated_bytes_0[] = {0x11u}; + constexpr uint8_t repeated_bytes_1[] = {0x22u, 0x23u}; + constexpr uint8_t repeated_bytes_2[] = {0x34u, 0x35u, 0x36u, 0x37u}; + constexpr uint8_t repeated_bytes_3[] = {0x48u, 0x49u, 0x4au}; + constexpr uint8_t sha256_bytes[] = { + 0x10u, 0x21u, 0x32u, 0x43u, 0x54u, 0x65u, 0x76u, 0x87u, 0x98u, 0xa9u, 0xbau, 0xcbu, 0xdcu, 0xedu, 0xfeu, 0x0fu, + 0x1eu, 0x2du, 0x3cu, 0x4bu, 0x5au, 0x69u, 0x78u, 0x87u, 0x96u, 0xa5u, 0xb4u, 0xc3u, 0xd2u, 0xe1u, 0xf0u, 0x0fu, + }; + constexpr int32_t integer_array_values[] = {101, 102, 103, 104, 105, 106, 107, 108}; + constexpr uint32_t fixed_integer_array_values[] = {901u, 902u, 903u}; + + static_assert(sizeof(byte_array) == ::test::ultimate::BYTE_ARRAY_CAP); + static_assert(sizeof(float_expr_array) == Message::FLOATISH_BOUND); + static_assert(sizeof(integer_array_values) / sizeof(integer_array_values[0]) == Message::INTEGER_ARRAY_CAP); + static_assert(sizeof(fixed_integer_array_values) / sizeof(fixed_integer_array_values[0]) == + Message::FIXED_INTEGER_ARRAY_CAP); + + inline void *smoke_allocate(void *, size_t size, size_t) noexcept { return malloc(size); } + + inline void smoke_deallocate(void *, void *ptr, size_t, size_t) noexcept { free(ptr); } + + inline Config::Context make_context() noexcept { + return Config::Context { + protocyte::Allocator {nullptr, smoke_allocate, smoke_deallocate}, + protocyte::Limits {}, + }; + } + + template constexpr protocyte::Span view_of(const uint8_t (&data)[N]) noexcept { + return protocyte::Span {data, N}; + } + + inline protocyte::Status assign_string(Config::String &out, protocyte::Span view) noexcept { + return out.assign(view); + } + + inline protocyte::Status assign_bytes(Config::Bytes &out, protocyte::Span view) noexcept { + return out.assign(view); + } + + template protocyte::Status append_bytes(Container &out, Config::Context &ctx, + protocyte::Span view) noexcept { + Config::Bytes value(&ctx); + if (const auto st = assign_bytes(value, view); !st) { + return st; + } + return out.push_back(protocyte::move(value)); + } + + inline protocyte::Status populate_required_fixed_array(Message &message, Config::Context &ctx) noexcept { + for (size_t i = 0; i < sizeof(fixed_integer_array_values) / sizeof(fixed_integer_array_values[0]); ++i) { + if (const auto st = message.mutable_fixed_integer_array().push_back(fixed_integer_array_values[i]); !st) { + return st; + } + } + if (const auto st = append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_0)); + !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_2)); + !st) { + return st; + } + return append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_3)); + } + + inline protocyte::Status populate_repeated_bytes_holder(RepeatedBytesHolder &value, Config::Context &ctx) noexcept { + if (const auto st = append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_0)); !st) { + return st; + } + if (const auto st = append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_1)); !st) { + return st; + } + return append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_2)); + } + + inline protocyte::Status populate_bounded_repeated_bytes_holder(BoundedRepeatedBytesHolder &value, + Config::Context &ctx) noexcept { + if (const auto st = append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_1)); !st) { + return st; + } + if (const auto st = append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_2)); !st) { + return st; + } + return append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_3)); + } + + inline protocyte::Status populate_fixed_repeated_bytes_holder(FixedRepeatedBytesHolder &value, + Config::Context &ctx) noexcept { + if (const auto st = append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_0)); !st) { + return st; + } + if (const auto st = append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_2)); !st) { + return st; + } + return append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_3)); + } + + inline protocyte::Status populate_nested2(Nested2 &value, protocyte::Span description, + float first, float second, InnerMode mode) noexcept { + if (const auto st = value.set_description(description); !st) { + return st; + } + if (const auto st = value.mutable_values().push_back(first); !st) { + return st; + } + if (const auto st = value.mutable_values().push_back(second); !st) { + return st; + } + return value.set_mode(mode); + } + + inline protocyte::Status populate_nested1(Nested1 &value, protocyte::Span name, + int32_t id) noexcept { + if (const auto st = value.set_name(name); !st) { + return st; + } + if (const auto st = value.set_id(id); !st) { + return st; + } + auto inner = value.ensure_inner(); + if (!inner) { + return protocyte::unexpected(inner.error()); + } + return populate_nested2(**inner, view_of(nested_description), 1.5f, 2.5f, InnerMode::B); + } + + inline protocyte::Status insert_map_str_int32(Message &message, Config::Context &ctx) noexcept { + Config::String key(&ctx); + if (const auto st = assign_string(key, view_of(map_key)); !st) { + return st; + } + return message.mutable_map_str_int32().insert_or_assign(protocyte::move(key), 301); + } + + inline protocyte::Status insert_map_int32_str(Message &message, Config::Context &ctx) noexcept { + Config::String value(&ctx); + if (const auto st = assign_string(value, view_of(map_value)); !st) { + return st; + } + return message.mutable_map_int32_str().insert_or_assign(302, protocyte::move(value)); + } + + inline protocyte::Status insert_map_bool_bytes(Message &message, Config::Context &ctx) noexcept { + Config::Bytes value(&ctx); + if (const auto st = assign_bytes(value, view_of(bool_bytes)); !st) { + return st; + } + return message.mutable_map_bool_bytes().insert_or_assign(true, protocyte::move(value)); + } + + inline protocyte::Status insert_map_uint64_msg(Message &message, Config::Context &ctx) noexcept { + Nested1 value(ctx); + if (const auto st = populate_nested1(value, view_of(nested_name), 330); !st) { + return st; + } + return message.mutable_map_uint64_msg().insert_or_assign(3300u, protocyte::move(value)); + } + + inline protocyte::Status insert_very_nested_map(Message &message, Config::Context &ctx) noexcept { + Config::String key(&ctx); + if (const auto st = assign_string(key, view_of(very_nested_key)); !st) { + return st; + } + Nested2 value(ctx); + if (const auto st = populate_nested2(value, view_of(nested_description), 3.5f, 4.5f, InnerMode::C); !st) { + return st; + } + return message.mutable_very_nested_map().insert_or_assign(protocyte::move(key), protocyte::move(value)); + } + + inline protocyte::Status populate_deep(Deep &value, Config::Context &ctx) noexcept { + if (const auto st = value.set_extreme(view_of(extreme_value)); !st) { + return st; + } + Config::String weird(&ctx); + if (const auto st = assign_string(weird, view_of(weird_value)); !st) { + return st; + } + if (const auto st = value.mutable_weird_map().insert_or_assign(7, protocyte::move(weird)); !st) { + return st; + } + return value.set_text(view_of(deep_text)); + } + + inline protocyte::Status populate_message(Message &message, Config::Context &ctx) noexcept { + if (const auto st = message.set_f_double(123.5); !st) { + return st; + } + if (const auto st = message.set_f_float(12.25f); !st) { + return st; + } + if (const auto st = message.set_f_int32(42); !st) { + return st; + } + if (const auto st = message.set_f_int64(42000000000ll); !st) { + return st; + } + if (const auto st = message.set_f_uint32(99u); !st) { + return st; + } + if (const auto st = message.set_f_uint64(99000000000ull); !st) { + return st; + } + if (const auto st = message.set_f_sint32(-17); !st) { + return st; + } + if (const auto st = message.set_f_sint64(-17000000000ll); !st) { + return st; + } + if (const auto st = message.set_f_fixed32(0x11223344u); !st) { + return st; + } + if (const auto st = message.set_f_fixed64(0x1122334455667788ull); !st) { + return st; + } + if (const auto st = message.set_f_sfixed32(-1234567); !st) { + return st; + } + if (const auto st = message.set_f_sfixed64(-1234567890123ll); !st) { + return st; + } + if (const auto st = message.set_f_bool(true); !st) { + return st; + } + if (const auto st = message.set_f_string(view_of(string_bytes)); !st) { + return st; + } + if (const auto st = message.set_f_bytes(view_of(bytes_data)); !st) { + return st; + } + if (const auto st = message.mutable_r_int32_unpacked().push_back(21); !st) { + return st; + } + if (const auto st = message.mutable_r_int32_unpacked().push_back(22); !st) { + return st; + } + if (const auto st = message.mutable_r_int32_packed().push_back(23); !st) { + return st; + } + if (const auto st = message.mutable_r_int32_packed().push_back(24); !st) { + return st; + } + if (const auto st = message.mutable_r_double().push_back(23.5); !st) { + return st; + } + if (const auto st = message.mutable_r_double().push_back(24.5); !st) { + return st; + } + if (const auto st = message.set_color(Color::GREEN); !st) { + return st; + } + + auto nested = message.ensure_nested1(); + if (!nested) { + return protocyte::unexpected(nested.error()); + } + if (const auto st = populate_nested1(**nested, view_of(nested_name), 25); !st) { + return st; + } + + if (const auto st = message.set_oneof_bytes(view_of(oneof_bytes)); !st) { + return st; + } + if (const auto st = insert_map_str_int32(message, ctx); !st) { + return st; + } + if (const auto st = insert_map_int32_str(message, ctx); !st) { + return st; + } + if (const auto st = insert_map_bool_bytes(message, ctx); !st) { + return st; + } + if (const auto st = insert_map_uint64_msg(message, ctx); !st) { + return st; + } + if (const auto st = insert_very_nested_map(message, ctx); !st) { + return st; + } + + auto recursive = message.ensure_recursive_self(); + if (!recursive) { + return protocyte::unexpected(recursive.error()); + } + if (const auto st = (*recursive)->set_f_string(view_of(recursive_string)); !st) { + return st; + } + if (const auto st = (*recursive)->set_f_int32(350); !st) { + return st; + } + if (const auto st = populate_required_fixed_array(**recursive, ctx); !st) { + return st; + } + + auto nested_item = message.mutable_lots_of_nested().emplace_back(ctx); + if (!nested_item) { + return protocyte::unexpected(nested_item.error()); + } + if (const auto st = populate_nested2(**nested_item, view_of(nested_description), 36.5f, 37.5f, InnerMode::A); + !st) { + return st; + } + + if (const auto st = message.mutable_colors().push_back(static_cast(Color::RED)); !st) { + return st; + } + if (const auto st = message.mutable_colors().push_back(static_cast(Color::BLUE)); !st) { + return st; + } + if (const auto st = message.set_opt_int32(38); !st) { + return st; + } + if (const auto st = message.set_opt_string(view_of(optional_string)); !st) { + return st; + } + if (const auto st = message.set_sha256(view_of(sha256_bytes)); !st) { + return st; + } + if (const auto st = message.set_byte_array(view_of(byte_array)); !st) { + return st; + } + if (const auto st = message.set_float_expr_array(view_of(float_expr_array)); !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_repeated_byte_array(), ctx, view_of(repeated_bytes_0)); !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_repeated_byte_array(), ctx, view_of(repeated_bytes_1)); !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_repeated_byte_array(), ctx, view_of(repeated_bytes_2)); !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_bounded_repeated_byte_array(), ctx, view_of(repeated_bytes_1)); + !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_bounded_repeated_byte_array(), ctx, view_of(repeated_bytes_2)); + !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_bounded_repeated_byte_array(), ctx, view_of(repeated_bytes_3)); + !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_0)); + !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_2)); + !st) { + return st; + } + if (const auto st = append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_3)); + !st) { + return st; + } + auto crazy_fixed_repeated = message.ensure_crazy_fixed_repeated_bytes(); + if (!crazy_fixed_repeated) { + return protocyte::unexpected(crazy_fixed_repeated.error()); + } + if (const auto st = populate_fixed_repeated_bytes_holder(**crazy_fixed_repeated, ctx); !st) { + return st; + } + + for (size_t i = 0; i < sizeof(integer_array_values) / sizeof(integer_array_values[0]); ++i) { + if (const auto st = message.mutable_integer_array().push_back(integer_array_values[i]); !st) { + return st; + } + } + for (size_t i = 0; i < sizeof(fixed_integer_array_values) / sizeof(fixed_integer_array_values[0]); ++i) { + if (const auto st = message.mutable_fixed_integer_array().push_back(fixed_integer_array_values[i]); !st) { + return st; + } + } + + auto deep = message.ensure_extreme_nesting(); + if (!deep) { + return protocyte::unexpected(deep.error()); + } + return populate_deep(**deep, ctx); + } + +} // namespace protocyte_smoke::fixture diff --git a/smoke/src/host_smoke.cpp b/smoke/src/host_smoke.cpp index 31e92fb..bf8eef9 100644 --- a/smoke/src/host_smoke.cpp +++ b/smoke/src/host_smoke.cpp @@ -14,6 +14,7 @@ #include "compat_cases.hpp" #include "cross_package.protocyte.hpp" #include "example.protocyte.hpp" +#include "host_fixture.hpp" #include "protocyte/runtime/runtime.hpp" namespace { @@ -446,18 +447,16 @@ namespace { } void assign_string(Config::String &out, protocyte::Span view) { - require_success(out.assign(view)); + require_success(protocyte_smoke::fixture::assign_string(out, view)); } void assign_bytes(Config::Bytes &out, protocyte::Span view) { - require_success(out.assign(view)); + require_success(protocyte_smoke::fixture::assign_bytes(out, view)); } template void append_bytes(Container &out, Config::Context &ctx, protocyte::Span view) { - Config::Bytes value(&ctx); - assign_bytes(value, view); - require_success(out.push_back(protocyte::move(value))); + require_success(protocyte_smoke::fixture::append_bytes(out, ctx, view)); } template @@ -554,12 +553,7 @@ namespace { } void populate_required_fixed_array(Message &message, Config::Context &ctx) { - for (size_t i = 0; i < sizeof(fixed_integer_array_values) / sizeof(fixed_integer_array_values[0]); ++i) { - require_success(message.mutable_fixed_integer_array().push_back(fixed_integer_array_values[i])); - } - append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_0)); - append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_2)); - append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_3)); + require_success(protocyte_smoke::fixture::populate_required_fixed_array(message, ctx)); } template void check_three_byte_entries(const Container &values, @@ -571,9 +565,7 @@ namespace { } void populate_repeated_bytes_holder(RepeatedBytesHolder &value, Config::Context &ctx) { - append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_0)); - append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_1)); - append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_2)); + require_success(protocyte_smoke::fixture::populate_repeated_bytes_holder(value, ctx)); } void check_repeated_bytes_holder(const RepeatedBytesHolder &value) { @@ -582,9 +574,7 @@ namespace { } void populate_bounded_repeated_bytes_holder(BoundedRepeatedBytesHolder &value, Config::Context &ctx) { - append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_1)); - append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_2)); - append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_3)); + require_success(protocyte_smoke::fixture::populate_bounded_repeated_bytes_holder(value, ctx)); } void check_bounded_repeated_bytes_holder(const BoundedRepeatedBytesHolder &value) { @@ -593,9 +583,7 @@ namespace { } void populate_fixed_repeated_bytes_holder(FixedRepeatedBytesHolder &value, Config::Context &ctx) { - append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_0)); - append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_2)); - append_bytes(value.mutable_values(), ctx, view_of(repeated_bytes_3)); + require_success(protocyte_smoke::fixture::populate_fixed_repeated_bytes_holder(value, ctx)); } void check_fixed_repeated_bytes_holder(const FixedRepeatedBytesHolder &value) { @@ -627,12 +615,9 @@ namespace { CHECK(value.mode() == mode); } - void populate_nested2(Nested2 &value, protocyte::Span description, float first, float second, - InnerMode mode) { - require_success(value.set_description(description)); - require_success(value.mutable_values().push_back(first)); - require_success(value.mutable_values().push_back(second)); - require_success(value.set_mode(mode)); + [[maybe_unused]] void populate_nested2(Nested2 &value, protocyte::Span description, + float first, float second, InnerMode mode) { + require_success(protocyte_smoke::fixture::populate_nested2(value, description, first, second, mode)); check_nested2(value, description, first, second, mode); } @@ -649,130 +634,36 @@ namespace { } void populate_nested1(Nested1 &value, protocyte::Span name, int32_t id) { - require_success(value.set_name(name)); - require_success(value.set_id(id)); - auto inner = value.ensure_inner(); - require_success(inner); - populate_nested2(**inner, view_of(nested_description), 1.5f, 2.5f, InnerMode::B); + require_success(protocyte_smoke::fixture::populate_nested1(value, name, id)); check_nested1(value, name, id); } void insert_map_str_int32(Message &message, Config::Context &ctx) { - Config::String key(&ctx); - assign_string(key, view_of(map_key)); - require_success(message.mutable_map_str_int32().insert_or_assign(protocyte::move(key), 301)); + require_success(protocyte_smoke::fixture::insert_map_str_int32(message, ctx)); } - void insert_map_int32_str(Message &message, Config::Context &ctx) { - Config::String value(&ctx); - assign_string(value, view_of(map_value)); - require_success(message.mutable_map_int32_str().insert_or_assign(302, protocyte::move(value))); + [[maybe_unused]] void insert_map_int32_str(Message &message, Config::Context &ctx) { + require_success(protocyte_smoke::fixture::insert_map_int32_str(message, ctx)); } - void insert_map_bool_bytes(Message &message, Config::Context &ctx) { - Config::Bytes value(&ctx); - assign_bytes(value, view_of(bool_bytes)); - require_success(message.mutable_map_bool_bytes().insert_or_assign(true, protocyte::move(value))); + [[maybe_unused]] void insert_map_bool_bytes(Message &message, Config::Context &ctx) { + require_success(protocyte_smoke::fixture::insert_map_bool_bytes(message, ctx)); } - void insert_map_uint64_msg(Message &message, Config::Context &ctx) { - Nested1 value(ctx); - populate_nested1(value, view_of(nested_name), 330); - require_success(message.mutable_map_uint64_msg().insert_or_assign(3300u, protocyte::move(value))); + [[maybe_unused]] void insert_map_uint64_msg(Message &message, Config::Context &ctx) { + require_success(protocyte_smoke::fixture::insert_map_uint64_msg(message, ctx)); } - void insert_very_nested_map(Message &message, Config::Context &ctx) { - Config::String key(&ctx); - assign_string(key, view_of(very_nested_key)); - Nested2 value(ctx); - populate_nested2(value, view_of(nested_description), 3.5f, 4.5f, InnerMode::C); - require_success( - message.mutable_very_nested_map().insert_or_assign(protocyte::move(key), protocyte::move(value))); + [[maybe_unused]] void insert_very_nested_map(Message &message, Config::Context &ctx) { + require_success(protocyte_smoke::fixture::insert_very_nested_map(message, ctx)); } - void populate_deep(Deep &value, Config::Context &ctx) { - require_success(value.set_extreme(view_of(extreme_value))); - Config::String weird(&ctx); - assign_string(weird, view_of(weird_value)); - require_success(value.mutable_weird_map().insert_or_assign(7, protocyte::move(weird))); - require_success(value.set_text(view_of(deep_text))); + [[maybe_unused]] void populate_deep(Deep &value, Config::Context &ctx) { + require_success(protocyte_smoke::fixture::populate_deep(value, ctx)); } void populate_message(Message &message, Config::Context &ctx) { - require_success(message.set_f_double(123.5)); - require_success(message.set_f_float(12.25f)); - require_success(message.set_f_int32(42)); - require_success(message.set_f_int64(42000000000ll)); - require_success(message.set_f_uint32(99u)); - require_success(message.set_f_uint64(99000000000ull)); - require_success(message.set_f_sint32(-17)); - require_success(message.set_f_sint64(-17000000000ll)); - require_success(message.set_f_fixed32(0x11223344u)); - require_success(message.set_f_fixed64(0x1122334455667788ull)); - require_success(message.set_f_sfixed32(-1234567)); - require_success(message.set_f_sfixed64(-1234567890123ll)); - require_success(message.set_f_bool(true)); - require_success(message.set_f_string(view_of(string_bytes))); - require_success(message.set_f_bytes(view_of(bytes_data))); - require_success(message.mutable_r_int32_unpacked().push_back(21)); - require_success(message.mutable_r_int32_unpacked().push_back(22)); - require_success(message.mutable_r_int32_packed().push_back(23)); - require_success(message.mutable_r_int32_packed().push_back(24)); - require_success(message.mutable_r_double().push_back(23.5)); - require_success(message.mutable_r_double().push_back(24.5)); - require_success(message.set_color(Color::GREEN)); - - auto nested = message.ensure_nested1(); - require_success(nested); - populate_nested1(**nested, view_of(nested_name), 25); - - require_success(message.set_oneof_bytes(view_of(oneof_bytes))); - insert_map_str_int32(message, ctx); - insert_map_int32_str(message, ctx); - insert_map_bool_bytes(message, ctx); - insert_map_uint64_msg(message, ctx); - insert_very_nested_map(message, ctx); - - auto recursive = message.ensure_recursive_self(); - require_success(recursive); - require_success((*recursive)->set_f_string(view_of(recursive_string))); - require_success((*recursive)->set_f_int32(350)); - populate_required_fixed_array(**recursive, ctx); - - auto nested_item = message.mutable_lots_of_nested().emplace_back(ctx); - require_success(nested_item); - populate_nested2(**nested_item, view_of(nested_description), 36.5f, 37.5f, InnerMode::A); - - require_success(message.mutable_colors().push_back(static_cast(Color::RED))); - require_success(message.mutable_colors().push_back(static_cast(Color::BLUE))); - require_success(message.set_opt_int32(38)); - require_success(message.set_opt_string(view_of(optional_string))); - require_success(message.set_sha256(view_of(sha256_bytes))); - require_success(message.set_byte_array(view_of(byte_array))); - require_success(message.set_float_expr_array(view_of(float_expr_array))); - append_bytes(message.mutable_repeated_byte_array(), ctx, view_of(repeated_bytes_0)); - append_bytes(message.mutable_repeated_byte_array(), ctx, view_of(repeated_bytes_1)); - append_bytes(message.mutable_repeated_byte_array(), ctx, view_of(repeated_bytes_2)); - append_bytes(message.mutable_bounded_repeated_byte_array(), ctx, view_of(repeated_bytes_1)); - append_bytes(message.mutable_bounded_repeated_byte_array(), ctx, view_of(repeated_bytes_2)); - append_bytes(message.mutable_bounded_repeated_byte_array(), ctx, view_of(repeated_bytes_3)); - append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_0)); - append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_2)); - append_bytes(message.mutable_fixed_repeated_byte_array(), ctx, view_of(repeated_bytes_3)); - auto crazy_fixed_repeated = message.ensure_crazy_fixed_repeated_bytes(); - require_success(crazy_fixed_repeated); - populate_fixed_repeated_bytes_holder(**crazy_fixed_repeated, ctx); - - for (size_t i = 0; i < sizeof(integer_array_values) / sizeof(integer_array_values[0]); ++i) { - require_success(message.mutable_integer_array().push_back(integer_array_values[i])); - } - for (size_t i = 0; i < sizeof(fixed_integer_array_values) / sizeof(fixed_integer_array_values[0]); ++i) { - require_success(message.mutable_fixed_integer_array().push_back(fixed_integer_array_values[i])); - } - - auto deep = message.ensure_extreme_nesting(); - require_success(deep); - populate_deep(**deep, ctx); + require_success(protocyte_smoke::fixture::populate_message(message, ctx)); } void check_maps(const Message &message) { diff --git a/smoke/src/protobuf_benchmark.cpp b/smoke/src/protobuf_benchmark.cpp new file mode 100644 index 0000000..3188842 --- /dev/null +++ b/smoke/src/protobuf_benchmark.cpp @@ -0,0 +1,202 @@ +#include + +#include +#include + +#include "benchmark.pb.h" +#include "host_fixture.hpp" + +namespace { + + using Message = test::benchmark::BenchmarkMessage; + using Fixture = protocyte_smoke::fixture::Message; + + std::string bytes_of(protocyte::Span view) { + return std::string {reinterpret_cast(view.data()), view.size()}; + } + + void populate_nested2(Message::NestedLevel1::NestedLevel2 *value, protocyte::Span description, + float first, float second, Message::NestedLevel1::NestedLevel2::InnerEnum mode) { + value->set_description(bytes_of(description)); + value->add_values(first); + value->add_values(second); + value->set_mode(mode); + } + + void populate_nested1(Message::NestedLevel1 *value, protocyte::Span name, int32_t id) { + value->set_name(bytes_of(name)); + value->set_id(id); + populate_nested2(value->mutable_inner(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::nested_description), 1.5f, 2.5f, + Message::NestedLevel1::NestedLevel2::B); + } + + void append_bytes(google::protobuf::RepeatedPtrField *values, + protocyte::Span view) { + values->Add(bytes_of(view)); + } + + void populate_fixed_repeated_bytes_holder(Message::FixedRepeatedBytesHolder *value) { + append_bytes(value->mutable_values(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_0)); + append_bytes(value->mutable_values(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_2)); + append_bytes(value->mutable_values(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_3)); + } + + void populate_message(Message *message) { + message->set_f_double(123.5); + message->set_f_float(12.25f); + message->set_f_int32(42); + message->set_f_int64(42000000000ll); + message->set_f_uint32(99u); + message->set_f_uint64(99000000000ull); + message->set_f_sint32(-17); + message->set_f_sint64(-17000000000ll); + message->set_f_fixed32(0x11223344u); + message->set_f_fixed64(0x1122334455667788ull); + message->set_f_sfixed32(-1234567); + message->set_f_sfixed64(-1234567890123ll); + message->set_f_bool(true); + message->set_f_string(bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::string_bytes))); + message->set_f_bytes(bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::bytes_data))); + message->add_r_int32_unpacked(21); + message->add_r_int32_unpacked(22); + message->add_r_int32_packed(23); + message->add_r_int32_packed(24); + message->add_r_double(23.5); + message->add_r_double(24.5); + message->set_color(Message::GREEN); + + populate_nested1(message->mutable_nested1(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::nested_name), 25); + message->set_oneof_bytes(bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::oneof_bytes))); + + (*message->mutable_map_str_int32())[bytes_of( + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::map_key))] = 301; + (*message->mutable_map_int32_str())[302] = + bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::map_value)); + (*message->mutable_map_bool_bytes())[true] = + bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::bool_bytes)); + populate_nested1(&(*message->mutable_map_uint64_msg())[3300u], + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::nested_name), 330); + populate_nested2(&(*message->mutable_very_nested_map())[bytes_of( + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::very_nested_key))], + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::nested_description), 3.5f, 4.5f, + Message::NestedLevel1::NestedLevel2::C); + + auto *recursive = message->mutable_recursive_self(); + recursive->set_f_string( + bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::recursive_string))); + recursive->set_f_int32(350); + recursive->mutable_fixed_integer_array()->Add( + protocyte_smoke::fixture::fixed_integer_array_values, + protocyte_smoke::fixture::fixed_integer_array_values + + (sizeof(protocyte_smoke::fixture::fixed_integer_array_values) / + sizeof(protocyte_smoke::fixture::fixed_integer_array_values[0]))); + append_bytes(recursive->mutable_fixed_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_0)); + append_bytes(recursive->mutable_fixed_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_2)); + append_bytes(recursive->mutable_fixed_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_3)); + + populate_nested2(message->add_lots_of_nested(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::nested_description), 36.5f, 37.5f, + Message::NestedLevel1::NestedLevel2::A); + + message->add_colors(Message::RED); + message->add_colors(Message::BLUE); + message->set_opt_int32(38); + message->set_opt_string(bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::optional_string))); + message->set_sha256(bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::sha256_bytes))); + message->set_byte_array(bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::byte_array))); + message->set_float_expr_array( + bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::float_expr_array))); + append_bytes(message->mutable_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_0)); + append_bytes(message->mutable_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_1)); + append_bytes(message->mutable_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_2)); + append_bytes(message->mutable_bounded_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_1)); + append_bytes(message->mutable_bounded_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_2)); + append_bytes(message->mutable_bounded_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_3)); + append_bytes(message->mutable_fixed_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_0)); + append_bytes(message->mutable_fixed_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_2)); + append_bytes(message->mutable_fixed_repeated_byte_array(), + protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::repeated_bytes_3)); + populate_fixed_repeated_bytes_holder(message->mutable_crazy_fixed_repeated_bytes()); + + message->mutable_integer_array()->Add(protocyte_smoke::fixture::integer_array_values, + protocyte_smoke::fixture::integer_array_values + + (sizeof(protocyte_smoke::fixture::integer_array_values) / + sizeof(protocyte_smoke::fixture::integer_array_values[0]))); + message->mutable_fixed_integer_array()->Add( + protocyte_smoke::fixture::fixed_integer_array_values, + protocyte_smoke::fixture::fixed_integer_array_values + + (sizeof(protocyte_smoke::fixture::fixed_integer_array_values) / + sizeof(protocyte_smoke::fixture::fixed_integer_array_values[0]))); + + auto *deep = message->mutable_extreme_nesting(); + deep->set_extreme(bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::extreme_value))); + (*deep->mutable_weird_map())[7] = + bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::weird_value)); + deep->set_text(bytes_of(protocyte_smoke::fixture::view_of(protocyte_smoke::fixture::deep_text))); + } + + void BM_ProtobufBenchmarkMessage_ByteSizeLong(benchmark::State &state) { + Message message; + populate_message(&message); + + for (auto _ : state) { + auto size = message.ByteSizeLong(); + benchmark::DoNotOptimize(size); + } + } + + void BM_ProtobufBenchmarkMessage_Serialize(benchmark::State &state) { + Message message; + populate_message(&message); + std::string encoded; + encoded.resize(message.ByteSizeLong()); + + for (auto _ : state) { + if (!message.SerializeToArray(encoded.data(), static_cast(encoded.size()))) { + state.SkipWithError("SerializeToArray failed"); + break; + } + benchmark::DoNotOptimize(encoded.data()); + benchmark::ClobberMemory(); + } + state.SetBytesProcessed(static_cast(state.iterations()) * static_cast(encoded.size())); + } + + void BM_ProtobufBenchmarkMessage_ParseFromArray(benchmark::State &state) { + Message message; + populate_message(&message); + std::string encoded = message.SerializeAsString(); + + for (auto _ : state) { + Message parsed; + if (!parsed.ParseFromArray(encoded.data(), static_cast(encoded.size()))) { + state.SkipWithError("ParseFromArray failed"); + break; + } + benchmark::DoNotOptimize(parsed.f_int32()); + benchmark::ClobberMemory(); + } + state.SetBytesProcessed(static_cast(state.iterations()) * static_cast(encoded.size())); + } + + BENCHMARK(BM_ProtobufBenchmarkMessage_ByteSizeLong); + BENCHMARK(BM_ProtobufBenchmarkMessage_Serialize); + BENCHMARK(BM_ProtobufBenchmarkMessage_ParseFromArray); + +} // namespace