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