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