From 25738f391bf4f7a583690d4a5c827d3803d2b6c3 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 11 Mar 2024 22:14:14 +0100 Subject: [PATCH] [BUILD] Provide LIKELY / UNLIKELY macros (#2580) * Contributes to #2572 * Restored support for __builtin_expect() * Typo --- api/include/opentelemetry/common/macros.h | 110 ++++++++++++++++++++-- api/include/opentelemetry/logs/logger.h | 10 +- exporters/otlp/src/otlp_log_recordable.cc | 10 +- sdk/src/logs/read_write_log_record.cc | 10 +- sdk/src/metrics/data/circular_buffer.cc | 7 +- 5 files changed, 129 insertions(+), 18 deletions(-) diff --git a/api/include/opentelemetry/common/macros.h b/api/include/opentelemetry/common/macros.h index 88ec2f0182..db1ca54a86 100644 --- a/api/include/opentelemetry/common/macros.h +++ b/api/include/opentelemetry/common/macros.h @@ -3,22 +3,112 @@ #pragma once -#if !defined(OPENTELEMETRY_LIKELY_IF) && defined(__cplusplus) +/* + Expected usage pattern: + + if OPENTELEMETRY_LIKELY_CONDITION (ptr != nullptr) + { + do_something_likely(); + } else { + do_something_unlikely(); + } + + This pattern works with gcc/clang and __builtin_expect(), + as well as with C++20. + It is unclear if __builtin_expect() will be deprecated + in favor of C++20 [[likely]] or not. + + OPENTELEMETRY_LIKELY_CONDITION is preferred over OPENTELEMETRY_LIKELY, + to be revisited when C++20 is required. +*/ + +#if !defined(OPENTELEMETRY_LIKELY_CONDITION) && defined(__cplusplus) +// Only use likely with C++20 +# if __cplusplus >= 202002L // GCC 9 has likely attribute but do not support declare it at the beginning of statement -# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9) -# if __has_cpp_attribute(likely) -# define OPENTELEMETRY_LIKELY_IF(...) \ - if (__VA_ARGS__) \ - [[likely]] +# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9) +# if __has_cpp_attribute(likely) +# define OPENTELEMETRY_LIKELY_CONDITION(C) (C) [[likely]] +# endif +# endif +# endif +#endif +#if !defined(OPENTELEMETRY_LIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__)) +// Only use if supported by the compiler +# define OPENTELEMETRY_LIKELY_CONDITION(C) (__builtin_expect(!!(C), true)) +#endif +#ifndef OPENTELEMETRY_LIKELY_CONDITION +// Do not use likely annotations +# define OPENTELEMETRY_LIKELY_CONDITION(C) (C) +#endif +#if !defined(OPENTELEMETRY_UNLIKELY_CONDITION) && defined(__cplusplus) +// Only use unlikely with C++20 +# if __cplusplus >= 202002L +// GCC 9 has unlikely attribute but do not support declare it at the beginning of statement +# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9) +# if __has_cpp_attribute(unlikely) +# define OPENTELEMETRY_UNLIKELY_CONDITION(C) (C) [[unlikely]] +# endif # endif # endif #endif -#if !defined(OPENTELEMETRY_LIKELY_IF) && (defined(__clang__) || defined(__GNUC__)) -# define OPENTELEMETRY_LIKELY_IF(...) if (__builtin_expect(!!(__VA_ARGS__), true)) +#if !defined(OPENTELEMETRY_UNLIKELY_CONDITION) && (defined(__clang__) || defined(__GNUC__)) +// Only use if supported by the compiler +# define OPENTELEMETRY_UNLIKELY_CONDITION(C) (__builtin_expect(!!(C), false)) #endif -#ifndef OPENTELEMETRY_LIKELY_IF -# define OPENTELEMETRY_LIKELY_IF(...) if (__VA_ARGS__) +#ifndef OPENTELEMETRY_UNLIKELY_CONDITION +// Do not use unlikely annotations +# define OPENTELEMETRY_UNLIKELY_CONDITION(C) (C) +#endif + +/* + Expected usage pattern: + + if (ptr != nullptr) + OPENTELEMETRY_LIKELY + { + do_something_likely(); + } else { + do_something_unlikely(); + } + + This pattern works starting with C++20. + See https://en.cppreference.com/w/cpp/language/attributes/likely + + Please use OPENTELEMETRY_LIKELY_CONDITION instead for now. +*/ + +#if !defined(OPENTELEMETRY_LIKELY) && defined(__cplusplus) +// Only use likely with C++20 +# if __cplusplus >= 202002L +// GCC 9 has likely attribute but do not support declare it at the beginning of statement +# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9) +# if __has_cpp_attribute(likely) +# define OPENTELEMETRY_LIKELY [[likely]] +# endif +# endif +# endif +#endif + +#ifndef OPENTELEMETRY_LIKELY +# define OPENTELEMETRY_LIKELY +#endif + +#if !defined(OPENTELEMETRY_UNLIKELY) && defined(__cplusplus) +// Only use unlikely with C++20 +# if __cplusplus >= 202002L +// GCC 9 has unlikely attribute but do not support declare it at the beginning of statement +# if defined(__has_cpp_attribute) && (defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 9) +# if __has_cpp_attribute(unlikely) +# define OPENTELEMETRY_UNLIKELY [[unlikely]] +# endif +# endif +# endif +#endif + +#ifndef OPENTELEMETRY_UNLIKELY +# define OPENTELEMETRY_UNLIKELY #endif /// \brief Declare variable as maybe unused diff --git a/api/include/opentelemetry/logs/logger.h b/api/include/opentelemetry/logs/logger.h index a2bd2c0bcf..403e884272 100644 --- a/api/include/opentelemetry/logs/logger.h +++ b/api/include/opentelemetry/logs/logger.h @@ -258,13 +258,19 @@ class Logger inline bool Enabled(Severity severity, const EventId &event_id) const noexcept { - OPENTELEMETRY_LIKELY_IF(Enabled(severity) == false) { return false; } + if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity)) + { + return false; + } return EnabledImplementation(severity, event_id); } inline bool Enabled(Severity severity, int64_t event_id) const noexcept { - OPENTELEMETRY_LIKELY_IF(Enabled(severity) == false) { return false; } + if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity)) + { + return false; + } return EnabledImplementation(severity, event_id); } diff --git a/exporters/otlp/src/otlp_log_recordable.cc b/exporters/otlp/src/otlp_log_recordable.cc index 7b86839dff..8acb4073d2 100644 --- a/exporters/otlp/src/otlp_log_recordable.cc +++ b/exporters/otlp/src/otlp_log_recordable.cc @@ -18,7 +18,10 @@ namespace otlp const opentelemetry::sdk::resource::Resource &OtlpLogRecordable::GetResource() const noexcept { - OPENTELEMETRY_LIKELY_IF(nullptr != resource_) { return *resource_; } + if OPENTELEMETRY_LIKELY_CONDITION (nullptr != resource_) + { + return *resource_; + } return opentelemetry::sdk::logs::ReadableLogRecord::GetDefaultResource(); } @@ -26,7 +29,10 @@ const opentelemetry::sdk::resource::Resource &OtlpLogRecordable::GetResource() c const opentelemetry::sdk::instrumentationscope::InstrumentationScope & OtlpLogRecordable::GetInstrumentationScope() const noexcept { - OPENTELEMETRY_LIKELY_IF(nullptr != instrumentation_scope_) { return *instrumentation_scope_; } + if OPENTELEMETRY_LIKELY_CONDITION (nullptr != instrumentation_scope_) + { + return *instrumentation_scope_; + } return opentelemetry::sdk::logs::ReadableLogRecord::GetDefaultInstrumentationScope(); } diff --git a/sdk/src/logs/read_write_log_record.cc b/sdk/src/logs/read_write_log_record.cc index e6dea3d9e4..1c2aabffe7 100644 --- a/sdk/src/logs/read_write_log_record.cc +++ b/sdk/src/logs/read_write_log_record.cc @@ -158,7 +158,10 @@ const std::unordered_map const opentelemetry::sdk::resource::Resource &ReadWriteLogRecord::GetResource() const noexcept { - OPENTELEMETRY_LIKELY_IF(nullptr != resource_) { return *resource_; } + if OPENTELEMETRY_LIKELY_CONDITION (nullptr != resource_) + { + return *resource_; + } return GetDefaultResource(); } @@ -172,7 +175,10 @@ void ReadWriteLogRecord::SetResource( const opentelemetry::sdk::instrumentationscope::InstrumentationScope & ReadWriteLogRecord::GetInstrumentationScope() const noexcept { - OPENTELEMETRY_LIKELY_IF(nullptr != instrumentation_scope_) { return *instrumentation_scope_; } + if OPENTELEMETRY_LIKELY_CONDITION (nullptr != instrumentation_scope_) + { + return *instrumentation_scope_; + } return GetDefaultInstrumentationScope(); } diff --git a/sdk/src/metrics/data/circular_buffer.cc b/sdk/src/metrics/data/circular_buffer.cc index 93d8fd6eeb..e2bd6e8ec0 100644 --- a/sdk/src/metrics/data/circular_buffer.cc +++ b/sdk/src/metrics/data/circular_buffer.cc @@ -21,7 +21,7 @@ struct AdaptingIntegerArrayIncrement uint64_t operator()(std::vector &backing) { const uint64_t result = backing[index] + count; - OPENTELEMETRY_LIKELY_IF(result <= uint64_t(std::numeric_limits::max())) + if OPENTELEMETRY_LIKELY_CONDITION (result <= uint64_t(std::numeric_limits::max())) { backing[index] = static_cast(result); return 0; @@ -76,7 +76,10 @@ struct AdaptingIntegerArrayCopy void AdaptingIntegerArray::Increment(size_t index, uint64_t count) { const uint64_t result = nostd::visit(AdaptingIntegerArrayIncrement{index, count}, backing_); - OPENTELEMETRY_LIKELY_IF(result == 0) { return; } + if OPENTELEMETRY_LIKELY_CONDITION (result == 0) + { + return; + } EnlargeToFit(result); Increment(index, count); }