blob: ab8d82c2799a3e0eb08e4080ea29baed85dfd139 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/syslog/cpp/macros.h>
#include <atomic>
#include <perftest/perftest.h>
// Measure the times taken by atomic memory operations in the uncontended
// case (when no other threads are accessing the memory location).
//
// These atomics are important building blocks for other operations, such
// as mutexes, so it is useful to know their approximate costs.
namespace {
// Measure the time taken by an atomic increment.
template <typename Type>
bool TestAtomicIncrement(perftest::RepeatState* state) {
std::atomic<Type> atomic_val(0);
while (state->KeepRunning()) {
++atomic_val;
// Prevent the compiler from optimizing away the atomic increment,
// which it could potentially do because atomic_val is not otherwise
// referenced.
perftest::DoNotOptimize(&atomic_val);
}
return true;
}
// Measure the time taken by an atomic compare-and-swap.
template <typename Type>
bool TestAtomicCmpxchg(perftest::RepeatState* state) {
std::atomic<Type> atomic_val(0);
Type x = 0;
while (state->KeepRunning()) {
FX_CHECK(atomic_val.compare_exchange_strong(x, x + 1));
++x;
perftest::DoNotOptimize(&atomic_val);
}
return true;
}
void RegisterTests() {
perftest::RegisterTest("Atomic/Increment/32bit", TestAtomicIncrement<uint32_t>);
perftest::RegisterTest("Atomic/Increment/64bit", TestAtomicIncrement<uint64_t>);
perftest::RegisterTest("Atomic/Cmpxchg/32bit", TestAtomicCmpxchg<uint32_t>);
perftest::RegisterTest("Atomic/Cmpxchg/64bit", TestAtomicCmpxchg<uint64_t>);
}
PERFTEST_CTOR(RegisterTests);
} // namespace