Align benchmark::State to a cacheline. (#1230)

* Align benchmark::State to a cacheline.

This can avoid interference with neighboring objects and stabilize
benchmark results.

* separate cachline definition from alignment attribute macro

Co-authored-by: Roman Lebedev <lebedev.ri@gmail.com>

---------

Co-authored-by: dominic <510002+dmah42@users.noreply.github.com>
Co-authored-by: Roman Lebedev <lebedev.ri@gmail.com>
This commit is contained in:
Chris Kennelly 2024-08-16 11:10:18 -04:00 committed by GitHub
parent 437fea4b54
commit 6126d2a205
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 41 additions and 2 deletions

View File

@ -290,11 +290,50 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
#define BENCHMARK_OVERRIDE #define BENCHMARK_OVERRIDE
#endif #endif
#if defined(__GNUC__)
// Determine the cacheline size based on architecture
#if defined(__i386__) || defined(__x86_64__)
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
#elif defined(__powerpc64__)
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 128
#elif defined(__aarch64__)
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
#elif defined(__arm__)
// Cache line sizes for ARM: These values are not strictly correct since
// cache line sizes depend on implementations, not architectures. There
// are even implementations with cache line sizes configurable at boot
// time.
#if defined(__ARM_ARCH_5T__)
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 32
#elif defined(__ARM_ARCH_7A__)
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
#endif // ARM_ARCH
#endif // arches
#endif // __GNUC__
#ifndef BENCHMARK_INTERNAL_CACHELINE_SIZE
// A reasonable default guess. Note that overestimates tend to waste more
// space, while underestimates tend to waste more time.
#define BENCHMARK_INTERNAL_CACHELINE_SIZE 64
#endif
#if defined(__GNUC__)
// Indicates that the declared object be cache aligned using
// `BENCHMARK_INTERNAL_CACHELINE_SIZE` (see above).
#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED \
__attribute__((aligned(BENCHMARK_INTERNAL_CACHELINE_SIZE)))
#elif defined(_MSC_VER)
#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED \
__declspec(align(BENCHMARK_INTERNAL_CACHELINE_SIZE))
#else
#define BENCHMARK_INTERNAL_CACHELINE_ALIGNED
#endif
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning(push) #pragma warning(push)
// C4251: <symbol> needs to have dll-interface to be used by clients of class // C4251: <symbol> needs to have dll-interface to be used by clients of class
#pragma warning(disable : 4251) #pragma warning(disable : 4251)
#endif #endif // _MSC_VER_
namespace benchmark { namespace benchmark {
class BenchmarkReporter; class BenchmarkReporter;
@ -759,7 +798,7 @@ enum Skipped
// State is passed to a running Benchmark and contains state for the // State is passed to a running Benchmark and contains state for the
// benchmark to use. // benchmark to use.
class BENCHMARK_EXPORT State { class BENCHMARK_EXPORT BENCHMARK_INTERNAL_CACHELINE_ALIGNED State {
public: public:
struct StateIterator; struct StateIterator;
friend struct StateIterator; friend struct StateIterator;