1 // Copyright 2022 The Abseil Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <string>
16
17 #include "absl/crc/crc32c.h"
18 #include "absl/crc/internal/crc32c.h"
19 #include "absl/memory/memory.h"
20 #include "absl/strings/string_view.h"
21 #include "benchmark/benchmark.h"
22
23 namespace {
24
TestString(size_t len)25 std::string TestString(size_t len) {
26 std::string result;
27 result.reserve(len);
28 for (size_t i = 0; i < len; ++i) {
29 result.push_back(static_cast<char>(i % 256));
30 }
31 return result;
32 }
33
BM_Calculate(benchmark::State & state)34 void BM_Calculate(benchmark::State& state) {
35 int len = state.range(0);
36 std::string data = TestString(len);
37 for (auto s : state) {
38 benchmark::DoNotOptimize(data);
39 absl::crc32c_t crc = absl::ComputeCrc32c(data);
40 benchmark::DoNotOptimize(crc);
41 }
42 }
43 BENCHMARK(BM_Calculate)->Arg(0)->Arg(1)->Arg(100)->Arg(10000)->Arg(500000);
44
BM_Extend(benchmark::State & state)45 void BM_Extend(benchmark::State& state) {
46 int len = state.range(0);
47 std::string extension = TestString(len);
48 absl::crc32c_t base = absl::crc32c_t{0xC99465AA}; // CRC32C of "Hello World"
49 for (auto s : state) {
50 benchmark::DoNotOptimize(base);
51 benchmark::DoNotOptimize(extension);
52 absl::crc32c_t crc = absl::ExtendCrc32c(base, extension);
53 benchmark::DoNotOptimize(crc);
54 }
55 }
56 BENCHMARK(BM_Extend)->Arg(0)->Arg(1)->Arg(100)->Arg(10000)->Arg(500000)->Arg(
57 100 * 1000 * 1000);
58
59 // Make working set >> CPU cache size to benchmark prefetches better
BM_ExtendCacheMiss(benchmark::State & state)60 void BM_ExtendCacheMiss(benchmark::State& state) {
61 int len = state.range(0);
62 constexpr int total = 300 * 1000 * 1000;
63 std::string extension = TestString(total);
64 absl::crc32c_t base = absl::crc32c_t{0xC99465AA}; // CRC32C of "Hello World"
65 for (auto s : state) {
66 for (int i = 0; i < total; i += len * 2) {
67 benchmark::DoNotOptimize(base);
68 benchmark::DoNotOptimize(extension);
69 absl::crc32c_t crc =
70 absl::ExtendCrc32c(base, absl::string_view(&extension[i], len));
71 benchmark::DoNotOptimize(crc);
72 }
73 }
74 state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * total / 2);
75 }
76 BENCHMARK(BM_ExtendCacheMiss)->Arg(10)->Arg(100)->Arg(1000)->Arg(100000);
77
BM_ExtendByZeroes(benchmark::State & state)78 void BM_ExtendByZeroes(benchmark::State& state) {
79 absl::crc32c_t base = absl::crc32c_t{0xC99465AA}; // CRC32C of "Hello World"
80 int num_zeroes = state.range(0);
81 for (auto s : state) {
82 benchmark::DoNotOptimize(base);
83 absl::crc32c_t crc = absl::ExtendCrc32cByZeroes(base, num_zeroes);
84 benchmark::DoNotOptimize(crc);
85 }
86 }
87 BENCHMARK(BM_ExtendByZeroes)
88 ->RangeMultiplier(10)
89 ->Range(1, 1000000)
90 ->RangeMultiplier(32)
91 ->Range(1, 1 << 20);
92
BM_UnextendByZeroes(benchmark::State & state)93 void BM_UnextendByZeroes(benchmark::State& state) {
94 absl::crc32c_t base = absl::crc32c_t{0xdeadbeef};
95 int num_zeroes = state.range(0);
96 for (auto s : state) {
97 benchmark::DoNotOptimize(base);
98 absl::crc32c_t crc =
99 absl::crc_internal::UnextendCrc32cByZeroes(base, num_zeroes);
100 benchmark::DoNotOptimize(crc);
101 }
102 }
103 BENCHMARK(BM_UnextendByZeroes)
104 ->RangeMultiplier(10)
105 ->Range(1, 1000000)
106 ->RangeMultiplier(32)
107 ->Range(1, 1 << 20);
108
BM_Concat(benchmark::State & state)109 void BM_Concat(benchmark::State& state) {
110 int string_b_len = state.range(0);
111 std::string string_b = TestString(string_b_len);
112
113 // CRC32C of "Hello World"
114 absl::crc32c_t crc_a = absl::crc32c_t{0xC99465AA};
115 absl::crc32c_t crc_b = absl::ComputeCrc32c(string_b);
116
117 for (auto s : state) {
118 benchmark::DoNotOptimize(crc_a);
119 benchmark::DoNotOptimize(crc_b);
120 benchmark::DoNotOptimize(string_b_len);
121 absl::crc32c_t crc_ab = absl::ConcatCrc32c(crc_a, crc_b, string_b_len);
122 benchmark::DoNotOptimize(crc_ab);
123 }
124 }
125 BENCHMARK(BM_Concat)
126 ->RangeMultiplier(10)
127 ->Range(1, 1000000)
128 ->RangeMultiplier(32)
129 ->Range(1, 1 << 20);
130
BM_Memcpy(benchmark::State & state)131 void BM_Memcpy(benchmark::State& state) {
132 int string_len = state.range(0);
133
134 std::string source = TestString(string_len);
135 auto dest = absl::make_unique<char[]>(string_len);
136
137 for (auto s : state) {
138 benchmark::DoNotOptimize(source);
139 absl::crc32c_t crc =
140 absl::MemcpyCrc32c(dest.get(), source.data(), source.size());
141 benchmark::DoNotOptimize(crc);
142 benchmark::DoNotOptimize(dest);
143 benchmark::DoNotOptimize(dest.get());
144 benchmark::DoNotOptimize(dest[0]);
145 }
146
147 state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
148 state.range(0));
149 }
150 BENCHMARK(BM_Memcpy)->Arg(0)->Arg(1)->Arg(100)->Arg(10000)->Arg(500000);
151
BM_RemoveSuffix(benchmark::State & state)152 void BM_RemoveSuffix(benchmark::State& state) {
153 int full_string_len = state.range(0);
154 int suffix_len = state.range(1);
155
156 std::string full_string = TestString(full_string_len);
157 std::string suffix = full_string.substr(
158 full_string_len - suffix_len, full_string_len);
159
160 absl::crc32c_t full_string_crc = absl::ComputeCrc32c(full_string);
161 absl::crc32c_t suffix_crc = absl::ComputeCrc32c(suffix);
162
163 for (auto s : state) {
164 benchmark::DoNotOptimize(full_string_crc);
165 benchmark::DoNotOptimize(suffix_crc);
166 benchmark::DoNotOptimize(suffix_len);
167 absl::crc32c_t crc = absl::RemoveCrc32cSuffix(full_string_crc, suffix_crc,
168 suffix_len);
169 benchmark::DoNotOptimize(crc);
170 }
171 }
172 BENCHMARK(BM_RemoveSuffix)
173 ->ArgPair(1, 1)
174 ->ArgPair(100, 10)
175 ->ArgPair(100, 100)
176 ->ArgPair(10000, 1)
177 ->ArgPair(10000, 100)
178 ->ArgPair(10000, 10000)
179 ->ArgPair(500000, 1)
180 ->ArgPair(500000, 100)
181 ->ArgPair(500000, 10000)
182 ->ArgPair(500000, 500000);
183 } // namespace
184