1 // Copyright 2017 The CRC32C Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
4
5 #include <cstddef>
6 #include <cstdint>
7
8 #include "crc32c/crc32c_config.h"
9
10 #include "benchmark/benchmark.h"
11
12 #if CRC32C_TESTS_BUILT_WITH_GLOG
13 #include "glog/logging.h"
14 #endif // CRC32C_TESTS_BUILT_WITH_GLOG
15
16 #include "./crc32c_arm64.h"
17 #include "./crc32c_arm64_check.h"
18 #include "./crc32c_internal.h"
19 #include "./crc32c_sse42.h"
20 #include "./crc32c_sse42_check.h"
21 #include "crc32c/crc32c.h"
22
23 class CRC32CBenchmark : public benchmark::Fixture {
24 public:
SetUp(const benchmark::State & state)25 void SetUp(const benchmark::State& state) override {
26 block_size_ = static_cast<size_t>(state.range(0));
27 block_data_ = std::string(block_size_, 'x');
28 block_buffer_ = reinterpret_cast<const uint8_t*>(block_data_.data());
29 }
30
31 protected:
32 std::string block_data_;
33 const uint8_t* block_buffer_;
34 size_t block_size_;
35 };
36
BENCHMARK_DEFINE_F(CRC32CBenchmark,Public)37 BENCHMARK_DEFINE_F(CRC32CBenchmark, Public)(benchmark::State& state) {
38 uint32_t crc = 0;
39 for (auto _ : state)
40 crc = crc32c::Extend(crc, block_buffer_, block_size_);
41 state.SetBytesProcessed(state.iterations() * block_size_);
42 }
43 BENCHMARK_REGISTER_F(CRC32CBenchmark, Public)
44 ->RangeMultiplier(16)
45 ->Range(256, 16777216); // Block size.
46
BENCHMARK_DEFINE_F(CRC32CBenchmark,Portable)47 BENCHMARK_DEFINE_F(CRC32CBenchmark, Portable)(benchmark::State& state) {
48 uint32_t crc = 0;
49 for (auto _ : state)
50 crc = crc32c::ExtendPortable(crc, block_buffer_, block_size_);
51 state.SetBytesProcessed(state.iterations() * block_size_);
52 }
53 BENCHMARK_REGISTER_F(CRC32CBenchmark, Portable)
54 ->RangeMultiplier(16)
55 ->Range(256, 16777216); // Block size.
56
57 #if HAVE_ARM64_CRC32C
58
BENCHMARK_DEFINE_F(CRC32CBenchmark,ArmCRC32C)59 BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmCRC32C)(benchmark::State& state) {
60 if (!crc32c::CanUseArm64Crc32()) {
61 state.SkipWithError("ARM CRC32C instructions not available or not enabled");
62 return;
63 }
64
65 uint32_t crc = 0;
66 for (auto _ : state)
67 crc = crc32c::ExtendArm64(crc, block_buffer_, block_size_);
68 state.SetBytesProcessed(state.iterations() * block_size_);
69 }
70 BENCHMARK_REGISTER_F(CRC32CBenchmark, ArmCRC32C)
71 ->RangeMultiplier(16)
72 ->Range(256, 16777216); // Block size.
73
74 #endif // HAVE_ARM64_CRC32C
75
76 #if HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
77
BENCHMARK_DEFINE_F(CRC32CBenchmark,Sse42)78 BENCHMARK_DEFINE_F(CRC32CBenchmark, Sse42)(benchmark::State& state) {
79 if (!crc32c::CanUseSse42()) {
80 state.SkipWithError("SSE4.2 instructions not available or not enabled");
81 return;
82 }
83
84 uint32_t crc = 0;
85 for (auto _ : state)
86 crc = crc32c::ExtendSse42(crc, block_buffer_, block_size_);
87 state.SetBytesProcessed(state.iterations() * block_size_);
88 }
89 BENCHMARK_REGISTER_F(CRC32CBenchmark, Sse42)
90 ->RangeMultiplier(16)
91 ->Range(256, 16777216); // Block size.
92
93 #endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
94
main(int argc,char ** argv)95 int main(int argc, char** argv) {
96 #if CRC32C_TESTS_BUILT_WITH_GLOG
97 google::InitGoogleLogging(argv[0]);
98 google::InstallFailureSignalHandler();
99 #endif // CRC32C_TESTS_BUILT_WITH_GLOG
100
101 benchmark::Initialize(&argc, argv);
102 benchmark::RunSpecifiedBenchmarks();
103 return 0;
104 }
105