1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/big_endian.h"
9 #include "base/check.h"
10 #include "base/containers/span.h"
11 #include "third_party/google_benchmark/src/include/benchmark/benchmark.h"
16 constexpr size_t kSize = 128 * 1024 * 1024;
17 int64_t aligned_bytes[kSize / sizeof(int64_t)];
20 char padding_to_cause_misalignment;
24 void DoNotOptimizeSpan(span<const char> range) {
25 // ::benchmark::DoNotOptimize() generates quite large code, so instead of
26 // calling it for every byte in the range, calculate `sum` which depends on
27 // every byte in the range and then call DoNotOptimise() on that.
29 for (char c : range) {
32 ::benchmark::DoNotOptimize(sum);
36 inline void WriteBigEndianCommon(::benchmark::State& state, char* const start) {
39 for (auto _ : state) {
40 WriteBigEndian(start + offset, value);
42 static_assert(kSize % sizeof(T) == 0);
43 if (offset == kSize) {
48 DoNotOptimizeSpan({start, kSize});
52 void BM_WriteBigEndianAligned(::benchmark::State& state) {
53 char* const start = reinterpret_cast<char*>(aligned_bytes);
54 CHECK(reinterpret_cast<uintptr_t>(start) % alignof(T) == 0);
55 WriteBigEndianCommon<T>(state, start);
59 void BM_WriteBigEndianMisaligned(::benchmark::State& state) {
60 char* const start = misaligned_bytes.bytes;
61 CHECK(reinterpret_cast<uintptr_t>(start) % alignof(T) != 0);
62 WriteBigEndianCommon<T>(state, start);
66 inline void ReadBigEndianCommon(::benchmark::State& state,
67 const uint8_t* const start) {
69 for (auto _ : state) {
71 ReadBigEndian(start + offset, &value);
72 ::benchmark::DoNotOptimize(value);
74 static_assert(kSize % sizeof(T) == 0);
75 if (offset == kSize) {
82 void BM_ReadBigEndianAligned(::benchmark::State& state) {
83 const uint8_t* const start = reinterpret_cast<uint8_t*>(aligned_bytes);
84 CHECK(reinterpret_cast<uintptr_t>(start) % alignof(T) == 0);
85 ReadBigEndianCommon<T>(state, start);
89 void BM_ReadBigEndianMisaligned(::benchmark::State& state) {
90 const uint8_t* const start =
91 reinterpret_cast<uint8_t*>(misaligned_bytes.bytes);
92 CHECK(reinterpret_cast<uintptr_t>(start) % alignof(T) != 0);
93 ReadBigEndianCommon<T>(state, start);
96 #define BENCHMARK_FOR_INT_TYPES(function) \
97 BENCHMARK(function<int16_t>)->MinWarmUpTime(1.0); \
98 BENCHMARK(function<uint16_t>)->MinWarmUpTime(1.0); \
99 BENCHMARK(function<int32_t>)->MinWarmUpTime(1.0); \
100 BENCHMARK(function<uint32_t>)->MinWarmUpTime(1.0); \
101 BENCHMARK(function<int64_t>)->MinWarmUpTime(1.0); \
102 BENCHMARK(function<uint64_t>)->MinWarmUpTime(1.0); \
103 typedef int force_semicolon
105 BENCHMARK_FOR_INT_TYPES(BM_WriteBigEndianAligned);
106 BENCHMARK_FOR_INT_TYPES(BM_WriteBigEndianMisaligned);
107 BENCHMARK_FOR_INT_TYPES(BM_ReadBigEndianAligned);
108 BENCHMARK_FOR_INT_TYPES(BM_ReadBigEndianMisaligned);
110 #undef BENCHMARK_FOR_INT_TYPES