Skip to content
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
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,21 @@ jobs:
run: cmake -S . -B build-bench -DLOGIT_BENCH_ENABLE=ON -DLOGIT_BENCH_WITH_SPDLOG=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DLOGIT_WITH_SYSLOG=ON -DLOGIT_WITH_WIN_EVENT_LOG=OFF
- name: Build benchmarks
# if: ${{ github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/stable') }}
run: cmake --build build-bench --target logit_bench logit_bench_flush_test logit_public_macro_bench logit_hotpath_bench logit_hotpath_bench_legacy benchmark_validation_test
run: cmake --build build-bench --target logit_bench logit_bench_flush_test logit_public_macro_bench logit_public_macro_formatted_bench logit_hotpath_bench logit_hotpath_bench_legacy benchmark_validation_test
- name: Run spdlog async flush regression
run: ./build-bench/logit_bench_flush_test
- name: Run public macro benchmark smoke
env:
LOGIT_PUBLIC_BENCH_TOTAL: 2000
LOGIT_PUBLIC_BENCH_PRODUCERS: 4
LOGIT_PUBLIC_BENCH_WARMUP: 200
run: ./build-bench/logit_public_macro_bench
- name: Run formatted public macro benchmark smoke
env:
LOGIT_PUBLIC_BENCH_TOTAL: 2000
LOGIT_PUBLIC_BENCH_PRODUCERS: 4
LOGIT_PUBLIC_BENCH_WARMUP: 200
run: ./build-bench/logit_public_macro_formatted_bench
- name: Run benchmark validation tests
run: ./build-bench/benchmark_validation_test
- name: Run logger hot-path A/B smoke
Expand Down
234 changes: 234 additions & 0 deletions bench/BenchmarkMetadata.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
#pragma once

#ifndef LOGIT_CPP_HEADER_BENCH_BENCHMARK_METADATA_HPP_INCLUDED
#define LOGIT_CPP_HEADER_BENCH_BENCHMARK_METADATA_HPP_INCLUDED

#include <cstddef>
#include <cstdlib>
#include <ostream>
#include <stdexcept>
#include <string>
#include <utility>

namespace logit_bench {

struct BenchmarkMetadata {
std::string source_commit;
std::string compiler;
std::string compiler_version;
std::string toolchain;
std::string cxx_standard;
std::string platform;
std::string build_type;
std::string architecture;
std::string machine_id;
std::string cpu_model;
std::string queue_capacity;
std::string queue_policy;
std::string latency_completion;
std::string flush_barrier;
};

inline std::string benchmark_env(const char* name, const char* fallback) {
if (const char* value = std::getenv(name)) {
if (*value != '\0') return value;
}
return fallback;
}

inline std::string benchmark_label(const char* name, const char* fallback) {
std::string value = benchmark_env(name, fallback);
for (char& character : value) {
if (character == ' ' || character == '\t' ||
character == '\r' || character == '\n') {
character = '_';
}
}
return value;
}

inline std::string benchmark_compiler() {
#if defined(_MSC_VER)
return "MSVC";
#elif defined(__clang__)
return "Clang";
#elif defined(__GNUC__)
return "GCC";
#else
return "unknown";
#endif
}

inline std::string benchmark_compiler_version() {
#if defined(_MSC_VER)
return std::to_string(_MSC_VER);
#elif defined(__clang__)
return std::to_string(__clang_major__) + "." +
std::to_string(__clang_minor__) + "." +
std::to_string(__clang_patchlevel__);
#elif defined(__GNUC__)
return std::to_string(__GNUC__) + "." +
std::to_string(__GNUC_MINOR__) + "." +
std::to_string(__GNUC_PATCHLEVEL__);
#else
return "unknown";
#endif
}

inline std::string benchmark_source_commit() {
if (const char* value = std::getenv("LOGIT_BENCH_COMMIT")) {
if (*value != '\0') return value;
}
if (const char* value = std::getenv("GITHUB_SHA")) {
if (*value != '\0') return value;
}
return "unknown";
}

inline std::string benchmark_cxx_standard() {
#if defined(_MSVC_LANG)
return std::to_string(_MSVC_LANG);
#else
return std::to_string(__cplusplus);
#endif
}

inline std::string benchmark_platform() {
#if defined(__EMSCRIPTEN__)
return "emscripten";
#elif defined(_WIN32)
return "windows";
#elif defined(__APPLE__)
return "macos";
#elif defined(__linux__)
return "linux";
#else
return "unknown";
#endif
}

inline std::string benchmark_architecture() {
#if defined(__EMSCRIPTEN__) && defined(__wasm32__)
return "wasm32";
#elif defined(_M_X64) || defined(__x86_64__)
return "x86_64";
#elif defined(_M_IX86) || defined(__i386__)
return "x86";
#elif defined(_M_ARM64) || defined(__aarch64__)
return "arm64";
#elif defined(_M_ARM) || defined(__arm__)
return "arm";
#else
return "unknown";
#endif
}

inline std::string benchmark_build_type() {
if (const char* value = std::getenv("LOGIT_BENCH_BUILD_TYPE")) {
if (*value != '\0') return value;
}
#ifdef LOGIT_BENCH_BUILD_TYPE
return LOGIT_BENCH_BUILD_TYPE;
#else
return "unknown";
#endif
}

inline BenchmarkMetadata make_benchmark_metadata(
std::string queue_capacity,
std::string queue_policy,
std::string latency_completion,
std::string flush_barrier) {
const std::string compiler = benchmark_compiler();
const std::string compiler_version = benchmark_compiler_version();
std::string toolchain = compiler + "-" + compiler_version;
toolchain = benchmark_label("LOGIT_BENCH_TOOLCHAIN", toolchain.c_str());
return BenchmarkMetadata{
benchmark_source_commit(),
compiler,
compiler_version,
std::move(toolchain),
benchmark_cxx_standard(),
benchmark_platform(),
benchmark_build_type(),
benchmark_architecture(),
benchmark_label("LOGIT_BENCH_MACHINE_ID", "unknown"),
benchmark_label("LOGIT_BENCH_CPU_MODEL", "unknown"),
std::move(queue_capacity),
std::move(queue_policy),
std::move(latency_completion),
std::move(flush_barrier)};
}

inline bool benchmark_value_unknown(const std::string& value) {
return value.empty() || value == "unknown";
}

inline void validate_comparable_metadata(const BenchmarkMetadata& metadata,
bool require_comparable) {
if (!require_comparable) return;

struct MetadataField {
const char* name;
const std::string* value;
bool allow_not_applicable;
};
const MetadataField values[] = {
{"source_commit", &metadata.source_commit, false},
{"compiler", &metadata.compiler, false},
{"compiler_version", &metadata.compiler_version, false},
{"toolchain", &metadata.toolchain, false},
{"cxx_standard", &metadata.cxx_standard, false},
{"platform", &metadata.platform, false},
{"build_type", &metadata.build_type, false},
{"architecture", &metadata.architecture, false},
{"machine_id", &metadata.machine_id, false},
{"cpu_model", &metadata.cpu_model, false},
{"queue_capacity", &metadata.queue_capacity, true},
{"queue_policy", &metadata.queue_policy, true},
{"latency_completion", &metadata.latency_completion, false},
{"flush_barrier", &metadata.flush_barrier, false}};

for (const auto& value : values) {
if (benchmark_value_unknown(*value.value) ||
(!value.allow_not_applicable && *value.value == "not-applicable")) {
throw std::runtime_error(
std::string("Comparable benchmark requires metadata field '") +
value.name + "'; set the corresponding LOGIT_BENCH_* value or disable "
"LOGIT_BENCH_REQUIRE_COMPARABLE");
}
}
}

inline void validate_comparable_metadata(const BenchmarkMetadata& metadata) {
const char* required = std::getenv("LOGIT_BENCH_REQUIRE_COMPARABLE");
validate_comparable_metadata(
metadata, required && std::string(required) == "1");
}

inline void print_benchmark_metadata(std::ostream& out,
const BenchmarkMetadata& metadata,
std::size_t total_messages,
std::size_t warmup_messages) {
out << "benchmark-fixture version=1"
<< " source_commit=" << metadata.source_commit
<< " compiler=" << metadata.compiler
<< " compiler_version=" << metadata.compiler_version
<< " toolchain=" << metadata.toolchain
<< " cxx_standard=" << metadata.cxx_standard
<< " platform=" << metadata.platform
<< " build_type=" << metadata.build_type
<< " architecture=" << metadata.architecture
<< " machine_id=" << metadata.machine_id
<< " cpu_model=" << metadata.cpu_model
<< " queue_capacity=" << metadata.queue_capacity
<< " queue_policy=" << metadata.queue_policy
<< " latency_completion=" << metadata.latency_completion
<< " flush_barrier=" << metadata.flush_barrier
<< " total=" << total_messages
<< " warmup=" << warmup_messages << '\n';
}

} // namespace logit_bench

#endif // LOGIT_CPP_HEADER_BENCH_BENCHMARK_METADATA_HPP_INCLUDED
13 changes: 13 additions & 0 deletions bench/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ endif()
add_executable(logit_bench ${LOGIT_BENCH_SOURCES})

target_include_directories(logit_bench PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(logit_bench PRIVATE LOGIT_BENCH_BUILD_TYPE=\"$<CONFIG>\")

target_compile_features(logit_bench PRIVATE cxx_std_17)

Expand All @@ -27,11 +28,23 @@ target_link_libraries(logit_bench PRIVATE log-it-cpp::log-it-cpp)

add_executable(logit_public_macro_bench public_macro_bench.cpp)
target_compile_features(logit_public_macro_bench PRIVATE cxx_std_17)
target_compile_definitions(logit_public_macro_bench PRIVATE LOGIT_BENCH_BUILD_TYPE=\"$<CONFIG>\")
target_link_libraries(logit_public_macro_bench PRIVATE log-it-cpp::log-it-cpp)
set_target_properties(logit_public_macro_bench PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)

add_executable(logit_public_macro_formatted_bench public_macro_bench.cpp)
target_compile_features(logit_public_macro_formatted_bench PRIVATE cxx_std_17)
target_compile_definitions(logit_public_macro_formatted_bench PRIVATE
LOGIT_PUBLIC_BENCH_FORMATTED=1
LOGIT_BENCH_BUILD_TYPE=\"$<CONFIG>\"
)
target_link_libraries(logit_public_macro_formatted_bench PRIVATE log-it-cpp::log-it-cpp)
set_target_properties(logit_public_macro_formatted_bench PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)

add_executable(logit_hotpath_bench logger_hotpath_bench.cpp)
target_compile_features(logit_hotpath_bench PRIVATE cxx_std_17)
target_link_libraries(logit_hotpath_bench PRIVATE log-it-cpp::log-it-cpp)
Expand Down
27 changes: 27 additions & 0 deletions bench/benchmark_validation_test.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "BenchmarkValidation.hpp"
#include "BenchmarkMetadata.hpp"

#include <stdexcept>
#include <string>
Expand Down Expand Up @@ -26,5 +27,31 @@ int main() {

validate_latency_csv_header(std::string(latency_csv_header()) + "\r");
validate_latency_csv_header(latency_csv_header());

const auto comparable = make_benchmark_metadata(
"8192", "block", "sink-entry", "all-prior-work-drained");
auto complete = comparable;
complete.source_commit = "test-commit";
complete.compiler = "test-compiler";
complete.compiler_version = "1";
complete.toolchain = "test-toolchain";
complete.cxx_standard = "201703";
complete.platform = "test-platform";
complete.build_type = "Release";
complete.architecture = "test-architecture";
complete.machine_id = "test-machine";
complete.cpu_model = "test-cpu";
validate_comparable_metadata(complete, true);

auto incomplete = complete;
incomplete.source_commit = "unknown";
bool rejected_unknown_metadata = false;
try {
validate_comparable_metadata(incomplete, true);
} catch (const std::runtime_error&) {
rejected_unknown_metadata = true;
}
if (!rejected_unknown_metadata) return 3;

return 0;
}
9 changes: 9 additions & 0 deletions bench/logit_bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "LatencyRecorder.hpp"
#include "BenchmarkValidation.hpp"
#include "BenchmarkMetadata.hpp"
#include "Scenario.hpp"
#include "adapters/LogItAdapter.hpp"

Expand Down Expand Up @@ -394,6 +395,14 @@ int main() {

const BenchFilter filter = load_filter();

const auto metadata = make_benchmark_metadata(
std::to_string(queue_capacity),
"block",
"sink-entry",
"all-prior-work-drained");
validate_comparable_metadata(metadata);
print_benchmark_metadata(std::cout, metadata, total_messages, warmup_messages);

LOGIT_SET_MAX_QUEUE(queue_capacity);
LOGIT_SET_QUEUE_POLICY(LOGIT_QUEUE_BLOCK);

Expand Down
Loading
Loading