1#ifndef SOURCEMETA_CORE_BENCHMARK_H_
2#define SOURCEMETA_CORE_BENCHMARK_H_
4#ifndef SOURCEMETA_CORE_BENCHMARK_EXPORT
5#include <sourcemeta/core/benchmark_export.h>
8#include <sourcemeta/core/preprocessor.h>
30namespace sourcemeta::core {
37#pragma warning(disable : 4251 4275)
52 struct [[maybe_unused]]
Value {};
61 Iterator() : remaining_{0}, parent_{nullptr} {}
65 : remaining_{parent->iterations_}, parent_{parent} {}
68 SOURCEMETA_FORCEINLINE
auto operator*() const ->
Value {
return {}; }
71 SOURCEMETA_FORCEINLINE
auto operator++() -> Iterator & {
72 this->remaining_ -= 1;
78 SOURCEMETA_FORCEINLINE
auto operator!=(
const Iterator &other)
const
80 if (this->remaining_ != other.remaining_) [[likely]] {
86 if (this->parent_ !=
nullptr) {
87 this->parent_->finish();
94 std::uint64_t remaining_;
95 BenchmarkState *parent_;
99 SOURCEMETA_FORCEINLINE
auto begin() -> Iterator {
return Iterator{
this}; }
103 SOURCEMETA_FORCEINLINE
auto end() -> Iterator {
113 [[nodiscard]] auto
real_time() const -> std::chrono::nanoseconds;
117 -> std::optional<std::chrono::nanoseconds>;
120 auto start() ->
void;
121 auto finish() ->
void;
123 std::uint64_t iterations_;
124 bool started_{
false};
125 bool finished_{
false};
126 std::chrono::steady_clock::time_point real_start_{};
127 std::chrono::nanoseconds real_elapsed_{0};
128 std::optional<std::chrono::nanoseconds> cpu_start_{std::nullopt};
129 std::optional<std::chrono::nanoseconds> cpu_elapsed_{std::nullopt};
135#if !defined(__clang__) && !defined(__GNUC__)
141SOURCEMETA_CORE_BENCHMARK_EXPORT
181template <
typename Type>
184#if defined(__clang__)
185 asm volatile(
"" :
"+r,m"(value) : :
"memory");
186#elif defined(__GNUC__)
187 if constexpr (std::is_trivially_copyable_v<Type> &&
188 sizeof(
Type) <=
sizeof(
void *)) {
189 asm volatile(
"" :
"+m,r"(value) : :
"memory");
191 asm volatile(
"" :
"+m"(value) : :
"memory");
193#elif defined(_MSC_VER)
216template <
typename Type>
219#if defined(__clang__)
220 asm volatile(
"" : :
"r,m"(value) :
"memory");
221#elif defined(__GNUC__)
222 if constexpr (std::is_trivially_copyable_v<Type> &&
223 sizeof(
Type) <=
sizeof(
void *)) {
224 asm volatile(
"" : :
"r,m"(value) :
"memory");
226 asm volatile(
"" : :
"m"(value) :
"memory");
228#elif defined(_MSC_VER)
242SOURCEMETA_CORE_BENCHMARK_EXPORT
250SOURCEMETA_CORE_BENCHMARK_EXPORT
267#define SOURCEMETA_CORE_BENCHMARK_REGISTER(name) \
268 static auto sourcemeta_benchmark_body_##name( \
269 ::sourcemeta::core::BenchmarkState &) \
271 [[maybe_unused]] static const int sourcemeta_benchmark_registration_##name = \
272 ::sourcemeta::core::benchmark_register( \
273 #name, __FILE__, __LINE__, &sourcemeta_benchmark_body_##name); \
274 static auto sourcemeta_benchmark_body_##name( \
275 ::sourcemeta::core::BenchmarkState &state) \
278#define BENCHMARK(name) SOURCEMETA_CORE_BENCHMARK_REGISTER(name)
auto iterations() const -> std::uint64_t
How many iterations this run was asked to perform.
BenchmarkState(const std::uint64_t iterations)
Prepare a run of the given number of iterations.
auto real_time() const -> std::chrono::nanoseconds
How long the iterations took on the clock.
auto measured() const -> bool
Whether the body actually iterated.
auto cpu_time() const -> std::optional< std::chrono::nanoseconds >
SOURCEMETA_CORE_BENCHMARK_EXPORT auto benchmark_run(int argc, char **argv) -> int
SOURCEMETA_CORE_BENCHMARK_EXPORT auto benchmark_use_char_pointer(const volatile char *pointer) -> void
SOURCEMETA_FORCEINLINE auto benchmark_do_not_optimize(Type &value) -> void
Definition benchmark.h:182
SOURCEMETA_CORE_BENCHMARK_EXPORT auto benchmark_register(std::string_view name, std::string_view file, int line, std::function< void(BenchmarkState &)> body) -> int
@ Type
The token type does not match the expected media type.
Definition jose_verify.h:216