crc32c_benchmark.cc (5987B)
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 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 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) 44 ->Arg(0) 45 ->Arg(1) 46 ->Arg(100) 47 ->Arg(2048) 48 ->Arg(10000) 49 ->Arg(500000); 50 51 void BM_Extend(benchmark::State& state) { 52 int len = state.range(0); 53 std::string extension = TestString(len); 54 absl::crc32c_t base = absl::crc32c_t{0xC99465AA}; // CRC32C of "Hello World" 55 for (auto s : state) { 56 benchmark::DoNotOptimize(base); 57 benchmark::DoNotOptimize(extension); 58 absl::crc32c_t crc = absl::ExtendCrc32c(base, extension); 59 benchmark::DoNotOptimize(crc); 60 } 61 } 62 BENCHMARK(BM_Extend) 63 ->Arg(0) 64 ->Arg(1) 65 ->Arg(100) 66 ->Arg(2048) 67 ->Arg(10000) 68 ->Arg(500000) 69 ->Arg(100 * 1000 * 1000); 70 71 // Make working set >> CPU cache size to benchmark prefetches better 72 void BM_ExtendCacheMiss(benchmark::State& state) { 73 int len = state.range(0); 74 constexpr int total = 300 * 1000 * 1000; 75 std::string extension = TestString(total); 76 absl::crc32c_t base = absl::crc32c_t{0xC99465AA}; // CRC32C of "Hello World" 77 for (auto s : state) { 78 for (int i = 0; i < total; i += len * 2) { 79 benchmark::DoNotOptimize(base); 80 benchmark::DoNotOptimize(extension); 81 absl::crc32c_t crc = 82 absl::ExtendCrc32c(base, absl::string_view(&extension[i], len)); 83 benchmark::DoNotOptimize(crc); 84 } 85 } 86 state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * total / 2); 87 } 88 BENCHMARK(BM_ExtendCacheMiss)->Arg(10)->Arg(100)->Arg(1000)->Arg(100000); 89 90 void BM_ExtendByZeroes(benchmark::State& state) { 91 absl::crc32c_t base = absl::crc32c_t{0xC99465AA}; // CRC32C of "Hello World" 92 int num_zeroes = state.range(0); 93 for (auto s : state) { 94 benchmark::DoNotOptimize(base); 95 absl::crc32c_t crc = absl::ExtendCrc32cByZeroes(base, num_zeroes); 96 benchmark::DoNotOptimize(crc); 97 } 98 } 99 BENCHMARK(BM_ExtendByZeroes) 100 ->RangeMultiplier(10) 101 ->Range(1, 1000000) 102 ->RangeMultiplier(32) 103 ->Range(1, 1 << 20); 104 105 void BM_UnextendByZeroes(benchmark::State& state) { 106 absl::crc32c_t base = absl::crc32c_t{0xdeadbeef}; 107 int num_zeroes = state.range(0); 108 for (auto s : state) { 109 benchmark::DoNotOptimize(base); 110 absl::crc32c_t crc = 111 absl::crc_internal::UnextendCrc32cByZeroes(base, num_zeroes); 112 benchmark::DoNotOptimize(crc); 113 } 114 } 115 BENCHMARK(BM_UnextendByZeroes) 116 ->RangeMultiplier(10) 117 ->Range(1, 1000000) 118 ->RangeMultiplier(32) 119 ->Range(1, 1 << 20); 120 121 void BM_Concat(benchmark::State& state) { 122 int string_b_len = state.range(0); 123 std::string string_b = TestString(string_b_len); 124 125 // CRC32C of "Hello World" 126 absl::crc32c_t crc_a = absl::crc32c_t{0xC99465AA}; 127 absl::crc32c_t crc_b = absl::ComputeCrc32c(string_b); 128 129 for (auto s : state) { 130 benchmark::DoNotOptimize(crc_a); 131 benchmark::DoNotOptimize(crc_b); 132 benchmark::DoNotOptimize(string_b_len); 133 absl::crc32c_t crc_ab = absl::ConcatCrc32c(crc_a, crc_b, string_b_len); 134 benchmark::DoNotOptimize(crc_ab); 135 } 136 } 137 BENCHMARK(BM_Concat) 138 ->RangeMultiplier(10) 139 ->Range(1, 1000000) 140 ->RangeMultiplier(32) 141 ->Range(1, 1 << 20); 142 143 void BM_Memcpy(benchmark::State& state) { 144 int string_len = state.range(0); 145 146 std::string source = TestString(string_len); 147 auto dest = absl::make_unique<char[]>(string_len); 148 149 for (auto s : state) { 150 benchmark::DoNotOptimize(source); 151 absl::crc32c_t crc = 152 absl::MemcpyCrc32c(dest.get(), source.data(), source.size()); 153 benchmark::DoNotOptimize(crc); 154 benchmark::DoNotOptimize(dest); 155 benchmark::DoNotOptimize(dest.get()); 156 benchmark::DoNotOptimize(dest[0]); 157 } 158 159 state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * 160 state.range(0)); 161 } 162 BENCHMARK(BM_Memcpy)->Arg(0)->Arg(1)->Arg(100)->Arg(2048)->Arg(10000)->Arg( 163 500000); 164 165 void BM_RemoveSuffix(benchmark::State& state) { 166 int full_string_len = state.range(0); 167 int suffix_len = state.range(1); 168 169 std::string full_string = TestString(full_string_len); 170 std::string suffix = full_string.substr( 171 full_string_len - suffix_len, full_string_len); 172 173 absl::crc32c_t full_string_crc = absl::ComputeCrc32c(full_string); 174 absl::crc32c_t suffix_crc = absl::ComputeCrc32c(suffix); 175 176 for (auto s : state) { 177 benchmark::DoNotOptimize(full_string_crc); 178 benchmark::DoNotOptimize(suffix_crc); 179 benchmark::DoNotOptimize(suffix_len); 180 absl::crc32c_t crc = absl::RemoveCrc32cSuffix(full_string_crc, suffix_crc, 181 suffix_len); 182 benchmark::DoNotOptimize(crc); 183 } 184 } 185 BENCHMARK(BM_RemoveSuffix) 186 ->ArgPair(1, 1) 187 ->ArgPair(100, 10) 188 ->ArgPair(100, 100) 189 ->ArgPair(10000, 1) 190 ->ArgPair(10000, 100) 191 ->ArgPair(10000, 10000) 192 ->ArgPair(500000, 1) 193 ->ArgPair(500000, 100) 194 ->ArgPair(500000, 10000) 195 ->ArgPair(500000, 500000); 196 } // namespace