/ src / crc32c / src / crc32c_benchmark.cc
crc32c_benchmark.cc
  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:
 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  
 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  
 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  
 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  
 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  
 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  }