// Copyright 2020 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

#include "snappy-test.h"

#include "benchmark/benchmark.h"

#include "snappy-internal.h"
#include "snappy-sinksource.h"
#include "snappy.h"
#include "snappy_test_data.h"

namespace snappy {

namespace {

void FilesAndLevels(benchmark::internal::Benchmark* benchmark) {
  for (int i = 0; i < ARRAYSIZE(kTestDataFiles); ++i) {
    for (int level = snappy::CompressionOptions::MinCompressionLevel();
         level <= snappy::CompressionOptions::MaxCompressionLevel(); ++level) {
      benchmark->ArgPair(i, level);
    }
  }
}

void BM_UFlat(benchmark::State& state) {
  // Pick file to process based on state.range(0).
  int file_index = state.range(0);

  CHECK_GE(file_index, 0);
  CHECK_LT(file_index, ARRAYSIZE(kTestDataFiles));
  std::string contents =
      ReadTestDataFile(kTestDataFiles[file_index].filename,
                       kTestDataFiles[file_index].size_limit);

  std::string zcontents;
  snappy::Compress(
      contents.data(), contents.size(), &zcontents,
      snappy::CompressionOptions{/*level=*/static_cast<int>(state.range(1))});
  char* dst = new char[contents.size()];

  for (auto s : state) {
    CHECK(snappy::RawUncompress(zcontents.data(), zcontents.size(), dst));
    benchmark::DoNotOptimize(dst);
  }
  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          static_cast<int64_t>(contents.size()));
  state.SetLabel(kTestDataFiles[file_index].label);

  delete[] dst;
}
BENCHMARK(BM_UFlat)->Apply(FilesAndLevels);

struct SourceFiles {
  SourceFiles() {
    for (int i = 0; i < kFiles; i++) {
      std::string contents = ReadTestDataFile(kTestDataFiles[i].filename,
                                              kTestDataFiles[i].size_limit);
      max_size = std::max(max_size, contents.size());
      sizes[i] = contents.size();
      snappy::Compress(contents.data(), contents.size(), &zcontents[i]);
    }
  }
  static constexpr int kFiles = ARRAYSIZE(kTestDataFiles);
  std::string zcontents[kFiles];
  size_t sizes[kFiles];
  size_t max_size = 0;
};

void BM_UFlatMedley(benchmark::State& state) {
  static const SourceFiles* const source = new SourceFiles();

  std::vector<char> dst(source->max_size);

  for (auto s : state) {
    for (int i = 0; i < SourceFiles::kFiles; i++) {
      CHECK(snappy::RawUncompress(source->zcontents[i].data(),
                                  source->zcontents[i].size(), dst.data()));
      benchmark::DoNotOptimize(dst);
    }
  }

  int64_t source_sizes = 0;
  for (int i = 0; i < SourceFiles::kFiles; i++) {
    source_sizes += static_cast<int64_t>(source->sizes[i]);
  }
  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          source_sizes);
}
BENCHMARK(BM_UFlatMedley);

void BM_UValidate(benchmark::State& state) {
  // Pick file to process based on state.range(0).
  int file_index = state.range(0);

  CHECK_GE(file_index, 0);
  CHECK_LT(file_index, ARRAYSIZE(kTestDataFiles));
  std::string contents =
      ReadTestDataFile(kTestDataFiles[file_index].filename,
                       kTestDataFiles[file_index].size_limit);

  std::string zcontents;
  snappy::Compress(
      contents.data(), contents.size(), &zcontents,
      snappy::CompressionOptions{/*level=*/static_cast<int>(state.range(1))});

  for (auto s : state) {
    CHECK(snappy::IsValidCompressedBuffer(zcontents.data(), zcontents.size()));
  }
  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          static_cast<int64_t>(contents.size()));
  state.SetLabel(kTestDataFiles[file_index].label);
}
BENCHMARK(BM_UValidate)->Apply(FilesAndLevels);

void BM_UValidateMedley(benchmark::State& state) {
  static const SourceFiles* const source = new SourceFiles();

  for (auto s : state) {
    for (int i = 0; i < SourceFiles::kFiles; i++) {
      CHECK(snappy::IsValidCompressedBuffer(source->zcontents[i].data(),
                                            source->zcontents[i].size()));
    }
  }

  int64_t source_sizes = 0;
  for (int i = 0; i < SourceFiles::kFiles; i++) {
    source_sizes += static_cast<int64_t>(source->sizes[i]);
  }
  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          source_sizes);
}
BENCHMARK(BM_UValidateMedley);

void BM_UIOVecSource(benchmark::State& state) {
  // Pick file to process based on state.range(0).
  int file_index = state.range(0);
  int level = state.range(1);

  CHECK_GE(file_index, 0);
  CHECK_LT(file_index, ARRAYSIZE(kTestDataFiles));
  std::string contents =
      ReadTestDataFile(kTestDataFiles[file_index].filename,
                       kTestDataFiles[file_index].size_limit);

  // Create `iovec`s of the `contents`.
  const int kNumEntries = 10;
  struct iovec iov[kNumEntries];
  size_t used_so_far = 0;
  for (int i = 0; i < kNumEntries; ++i) {
    iov[i].iov_base = const_cast<char*>(contents.data()) + used_so_far;
    if (used_so_far == contents.size()) {
      iov[i].iov_len = 0;
      continue;
    }
    if (i == kNumEntries - 1) {
      iov[i].iov_len = contents.size() - used_so_far;
    } else {
      iov[i].iov_len = contents.size() / kNumEntries;
    }
    used_so_far += iov[i].iov_len;
  }

  char* dst = new char[snappy::MaxCompressedLength(contents.size())];
  size_t zsize = 0;
  for (auto s : state) {
    snappy::RawCompressFromIOVec(
        iov, contents.size(), dst, &zsize,
        snappy::CompressionOptions{/*level=*/static_cast<int>(level)});
    benchmark::DoNotOptimize(iov);
  }
  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          static_cast<int64_t>(contents.size()));
  const double compression_ratio =
      static_cast<double>(zsize) / std::max<size_t>(1, contents.size());
  state.SetLabel(StrFormat("%s (%.2f %%)", kTestDataFiles[file_index].label,
                           100.0 * compression_ratio));
  VLOG(0) << StrFormat("compression for %s: %d -> %d bytes",
                       kTestDataFiles[file_index].label, contents.size(),
                       zsize);

  delete[] dst;
}
BENCHMARK(BM_UIOVecSource)->Apply(FilesAndLevels);

void BM_UIOVecSink(benchmark::State& state) {
  // Pick file to process based on state.range(0).
  int file_index = state.range(0);

  CHECK_GE(file_index, 0);
  CHECK_LT(file_index, ARRAYSIZE(kTestDataFiles));
  std::string contents =
      ReadTestDataFile(kTestDataFiles[file_index].filename,
                       kTestDataFiles[file_index].size_limit);

  std::string zcontents;
  snappy::Compress(contents.data(), contents.size(), &zcontents);

  // Uncompress into an iovec containing ten entries.
  const int kNumEntries = 10;
  struct iovec iov[kNumEntries];
  char *dst = new char[contents.size()];
  size_t used_so_far = 0;
  for (int i = 0; i < kNumEntries; ++i) {
    iov[i].iov_base = dst + used_so_far;
    if (used_so_far == contents.size()) {
      iov[i].iov_len = 0;
      continue;
    }

    if (i == kNumEntries - 1) {
      iov[i].iov_len = contents.size() - used_so_far;
    } else {
      iov[i].iov_len = contents.size() / kNumEntries;
    }
    used_so_far += iov[i].iov_len;
  }

  for (auto s : state) {
    CHECK(snappy::RawUncompressToIOVec(zcontents.data(), zcontents.size(), iov,
                                       kNumEntries));
    benchmark::DoNotOptimize(iov);
  }
  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          static_cast<int64_t>(contents.size()));
  state.SetLabel(kTestDataFiles[file_index].label);

  delete[] dst;
}
BENCHMARK(BM_UIOVecSink)->DenseRange(0, 4);

void BM_UFlatSink(benchmark::State& state) {
  // Pick file to process based on state.range(0).
  int file_index = state.range(0);

  CHECK_GE(file_index, 0);
  CHECK_LT(file_index, ARRAYSIZE(kTestDataFiles));
  std::string contents =
      ReadTestDataFile(kTestDataFiles[file_index].filename,
                       kTestDataFiles[file_index].size_limit);

  std::string zcontents;
  snappy::Compress(
      contents.data(), contents.size(), &zcontents,
      snappy::CompressionOptions{/*level=*/static_cast<int>(state.range(1))});
  char* dst = new char[contents.size()];

  for (auto s : state) {
    snappy::ByteArraySource source(zcontents.data(), zcontents.size());
    snappy::UncheckedByteArraySink sink(dst);
    CHECK(snappy::Uncompress(&source, &sink));
    benchmark::DoNotOptimize(sink);
  }
  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          static_cast<int64_t>(contents.size()));
  state.SetLabel(kTestDataFiles[file_index].label);

  std::string s(dst, contents.size());
  CHECK_EQ(contents, s);

  delete[] dst;
}

BENCHMARK(BM_UFlatSink)->Apply(FilesAndLevels);

void BM_ZFlat(benchmark::State& state) {
  // Pick file to process based on state.range(0).
  int file_index = state.range(0);
  int level = state.range(1);

  CHECK_GE(file_index, 0);
  CHECK_LT(file_index, ARRAYSIZE(kTestDataFiles));
  std::string contents =
      ReadTestDataFile(kTestDataFiles[file_index].filename,
                       kTestDataFiles[file_index].size_limit);
  char* dst = new char[snappy::MaxCompressedLength(contents.size())];

  size_t zsize = 0;
  for (auto s : state) {
    snappy::RawCompress(
        contents.data(), contents.size(), dst, &zsize,
        snappy::CompressionOptions{/*level=*/static_cast<int>(level)});
    benchmark::DoNotOptimize(dst);
  }
  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          static_cast<int64_t>(contents.size()));
  const double compression_ratio =
      static_cast<double>(zsize) / std::max<size_t>(1, contents.size());
  state.SetLabel(StrFormat("%s (%.2f %%)", kTestDataFiles[file_index].label,
                           100.0 * compression_ratio));
  VLOG(0) << StrFormat("compression for %s: %d -> %d bytes",
                       kTestDataFiles[file_index].label, contents.size(),
                       zsize);
  delete[] dst;
}

BENCHMARK(BM_ZFlat)->Apply(FilesAndLevels);

void BM_ZFlatAll(benchmark::State& state) {
  const int num_files = ARRAYSIZE(kTestDataFiles);
  int level = state.range(0);

  std::vector<std::string> contents(num_files);
  std::vector<char*> dst(num_files);

  int64_t total_contents_size = 0;
  for (int i = 0; i < num_files; ++i) {
    contents[i] = ReadTestDataFile(kTestDataFiles[i].filename,
                                   kTestDataFiles[i].size_limit);
    dst[i] = new char[snappy::MaxCompressedLength(contents[i].size())];
    total_contents_size += contents[i].size();
  }

  size_t zsize = 0;
  for (auto s : state) {
    for (int i = 0; i < num_files; ++i) {
      snappy::RawCompress(
          contents[i].data(), contents[i].size(), dst[i], &zsize,
          snappy::CompressionOptions{/*level=*/static_cast<int>(level)});
      benchmark::DoNotOptimize(dst);
    }
  }

  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          total_contents_size);

  for (char* dst_item : dst) {
    delete[] dst_item;
  }
  state.SetLabel(StrFormat("%d kTestDataFiles", num_files));
}
BENCHMARK(BM_ZFlatAll)->DenseRange(1, 2);

void BM_ZFlatIncreasingTableSize(benchmark::State& state) {
  CHECK_GT(ARRAYSIZE(kTestDataFiles), 0);
  int level = state.range(0);
  const std::string base_content = ReadTestDataFile(
      kTestDataFiles[0].filename, kTestDataFiles[0].size_limit);

  std::vector<std::string> contents;
  std::vector<char*> dst;
  int64_t total_contents_size = 0;
  for (int table_bits = kMinHashTableBits; table_bits <= kMaxHashTableBits;
       ++table_bits) {
    std::string content = base_content;
    content.resize(1 << table_bits);
    dst.push_back(new char[snappy::MaxCompressedLength(content.size())]);
    total_contents_size += content.size();
    contents.push_back(std::move(content));
  }

  size_t zsize = 0;
  for (auto s : state) {
    for (size_t i = 0; i < contents.size(); ++i) {
      snappy::RawCompress(
          contents[i].data(), contents[i].size(), dst[i], &zsize,
          snappy::CompressionOptions{/*level=*/static_cast<int>(level)});
      benchmark::DoNotOptimize(dst);
    }
  }

  state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                          total_contents_size);

  for (char* dst_item : dst) {
    delete[] dst_item;
  }
  state.SetLabel(StrFormat("%d tables", contents.size()));
}
BENCHMARK(BM_ZFlatIncreasingTableSize)->DenseRange(1, 2);

}  // namespace

}  // namespace snappy
