| // Copyright 2022 The Abseil Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <memory> | |
| #include <string> | |
| #include "absl/crc/crc32c.h" | |
| #include "absl/crc/internal/crc32c.h" | |
| #include "absl/memory/memory.h" | |
| #include "absl/strings/string_view.h" | |
| #include "benchmark/benchmark.h" | |
| namespace { | |
| std::string TestString(size_t len) { | |
| std::string result; | |
| result.reserve(len); | |
| for (size_t i = 0; i < len; ++i) { | |
| result.push_back(static_cast<char>(i % 256)); | |
| } | |
| return result; | |
| } | |
| void BM_Calculate(benchmark::State& state) { | |
| int len = state.range(0); | |
| std::string data = TestString(len); | |
| for (auto s : state) { | |
| benchmark::DoNotOptimize(data); | |
| absl::crc32c_t crc = absl::ComputeCrc32c(data); | |
| benchmark::DoNotOptimize(crc); | |
| } | |
| } | |
| BENCHMARK(BM_Calculate) | |
| ->Arg(0) | |
| ->Arg(1) | |
| ->Arg(100) | |
| ->Arg(2048) | |
| ->Arg(10000) | |
| ->Arg(500000); | |
| void BM_Extend(benchmark::State& state) { | |
| int len = state.range(0); | |
| std::string extension = TestString(len); | |
| absl::crc32c_t base = absl::crc32c_t{0xC99465AA}; // CRC32C of "Hello World" | |
| for (auto s : state) { | |
| benchmark::DoNotOptimize(base); | |
| benchmark::DoNotOptimize(extension); | |
| absl::crc32c_t crc = absl::ExtendCrc32c(base, extension); | |
| benchmark::DoNotOptimize(crc); | |
| } | |
| } | |
| BENCHMARK(BM_Extend) | |
| ->Arg(0) | |
| ->Arg(1) | |
| ->Arg(100) | |
| ->Arg(2048) | |
| ->Arg(10000) | |
| ->Arg(500000) | |
| ->Arg(100 * 1000 * 1000); | |
| // Make working set >> CPU cache size to benchmark prefetches better | |
| void BM_ExtendCacheMiss(benchmark::State& state) { | |
| int len = state.range(0); | |
| constexpr int total = 300 * 1000 * 1000; | |
| std::string extension = TestString(total); | |
| absl::crc32c_t base = absl::crc32c_t{0xC99465AA}; // CRC32C of "Hello World" | |
| for (auto s : state) { | |
| for (int i = 0; i < total; i += len * 2) { | |
| benchmark::DoNotOptimize(base); | |
| benchmark::DoNotOptimize(extension); | |
| absl::crc32c_t crc = | |
| absl::ExtendCrc32c(base, absl::string_view(&extension[i], len)); | |
| benchmark::DoNotOptimize(crc); | |
| } | |
| } | |
| state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * total / 2); | |
| } | |
| BENCHMARK(BM_ExtendCacheMiss)->Arg(10)->Arg(100)->Arg(1000)->Arg(100000); | |
| void BM_ExtendByZeroes(benchmark::State& state) { | |
| absl::crc32c_t base = absl::crc32c_t{0xC99465AA}; // CRC32C of "Hello World" | |
| int num_zeroes = state.range(0); | |
| for (auto s : state) { | |
| benchmark::DoNotOptimize(base); | |
| absl::crc32c_t crc = absl::ExtendCrc32cByZeroes(base, num_zeroes); | |
| benchmark::DoNotOptimize(crc); | |
| } | |
| } | |
| BENCHMARK(BM_ExtendByZeroes) | |
| ->RangeMultiplier(10) | |
| ->Range(1, 1000000) | |
| ->RangeMultiplier(32) | |
| ->Range(1, 1 << 20); | |
| void BM_UnextendByZeroes(benchmark::State& state) { | |
| absl::crc32c_t base = absl::crc32c_t{0xdeadbeef}; | |
| int num_zeroes = state.range(0); | |
| for (auto s : state) { | |
| benchmark::DoNotOptimize(base); | |
| absl::crc32c_t crc = | |
| absl::crc_internal::UnextendCrc32cByZeroes(base, num_zeroes); | |
| benchmark::DoNotOptimize(crc); | |
| } | |
| } | |
| BENCHMARK(BM_UnextendByZeroes) | |
| ->RangeMultiplier(10) | |
| ->Range(1, 1000000) | |
| ->RangeMultiplier(32) | |
| ->Range(1, 1 << 20); | |
| void BM_Concat(benchmark::State& state) { | |
| int string_b_len = state.range(0); | |
| std::string string_b = TestString(string_b_len); | |
| // CRC32C of "Hello World" | |
| absl::crc32c_t crc_a = absl::crc32c_t{0xC99465AA}; | |
| absl::crc32c_t crc_b = absl::ComputeCrc32c(string_b); | |
| for (auto s : state) { | |
| benchmark::DoNotOptimize(crc_a); | |
| benchmark::DoNotOptimize(crc_b); | |
| benchmark::DoNotOptimize(string_b_len); | |
| absl::crc32c_t crc_ab = absl::ConcatCrc32c(crc_a, crc_b, string_b_len); | |
| benchmark::DoNotOptimize(crc_ab); | |
| } | |
| } | |
| BENCHMARK(BM_Concat) | |
| ->RangeMultiplier(10) | |
| ->Range(1, 1000000) | |
| ->RangeMultiplier(32) | |
| ->Range(1, 1 << 20); | |
| void BM_Memcpy(benchmark::State& state) { | |
| int string_len = state.range(0); | |
| std::string source = TestString(string_len); | |
| auto dest = std::make_unique<char[]>(string_len); | |
| for (auto s : state) { | |
| benchmark::DoNotOptimize(source); | |
| absl::crc32c_t crc = | |
| absl::MemcpyCrc32c(dest.get(), source.data(), source.size()); | |
| benchmark::DoNotOptimize(crc); | |
| benchmark::DoNotOptimize(dest); | |
| benchmark::DoNotOptimize(dest.get()); | |
| benchmark::DoNotOptimize(dest[0]); | |
| } | |
| state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * | |
| state.range(0)); | |
| } | |
| BENCHMARK(BM_Memcpy)->Arg(0)->Arg(1)->Arg(100)->Arg(2048)->Arg(10000)->Arg( | |
| 500000); | |
| void BM_RemoveSuffix(benchmark::State& state) { | |
| int full_string_len = state.range(0); | |
| int suffix_len = state.range(1); | |
| std::string full_string = TestString(full_string_len); | |
| std::string suffix = full_string.substr( | |
| full_string_len - suffix_len, full_string_len); | |
| absl::crc32c_t full_string_crc = absl::ComputeCrc32c(full_string); | |
| absl::crc32c_t suffix_crc = absl::ComputeCrc32c(suffix); | |
| for (auto s : state) { | |
| benchmark::DoNotOptimize(full_string_crc); | |
| benchmark::DoNotOptimize(suffix_crc); | |
| benchmark::DoNotOptimize(suffix_len); | |
| absl::crc32c_t crc = absl::RemoveCrc32cSuffix(full_string_crc, suffix_crc, | |
| suffix_len); | |
| benchmark::DoNotOptimize(crc); | |
| } | |
| } | |
| BENCHMARK(BM_RemoveSuffix) | |
| ->ArgPair(1, 1) | |
| ->ArgPair(100, 10) | |
| ->ArgPair(100, 100) | |
| ->ArgPair(10000, 1) | |
| ->ArgPair(10000, 100) | |
| ->ArgPair(10000, 10000) | |
| ->ArgPair(500000, 1) | |
| ->ArgPair(500000, 100) | |
| ->ArgPair(500000, 10000) | |
| ->ArgPair(500000, 500000); | |
| } // namespace |