yams/tests/benchmarks/storage_throughput_bench.cpp

95 lines
3.1 KiB
C++

#include <cstddef>
#include <filesystem>
#include <memory>
#include <string>
#include <system_error>
#include <vector>
#include <benchmark/benchmark.h>
#include "../common/test_data_generator.h"
#include "../common/test_helpers_catch2.h"
#include <yams/storage/storage_engine.h>
namespace {
class StorageFixture : public benchmark::Fixture {
public:
void SetUp(const benchmark::State& state) override {
tempDir_ = yams::test::make_temp_dir("yams_bench_storage_");
yams::storage::StorageConfig cfg;
cfg.basePath = tempDir_;
cfg.shardDepth = 2;
cfg.mutexPoolSize = 128;
engine_ = std::make_unique<yams::storage::StorageEngine>(cfg);
auto gen = yams::test::TestDataGenerator();
const auto dataSize = static_cast<size_t>(state.range(0));
data_ = gen.generateRandomBytes(dataSize);
// 64-char hex hash for valid storage key
hash_ = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
std::to_string(state.range(0) / 1024);
hash_ = hash_.substr(0, 64);
// Pre-store data for Retrieve benchmarks.
auto storeResult = engine_->store(hash_, data_);
if (!storeResult) {
throw std::runtime_error("pre-store failed for retrieve benchmark");
}
}
void TearDown(const benchmark::State&) override {
engine_.reset();
std::error_code ec;
std::filesystem::remove_all(tempDir_, ec);
}
protected:
std::filesystem::path tempDir_;
std::unique_ptr<yams::storage::StorageEngine> engine_;
std::vector<std::byte> data_;
std::string hash_;
};
BENCHMARK_DEFINE_F(StorageFixture, Store)(benchmark::State& state) {
int iter = 0;
for (auto _ : state) {
// Use unique 64-char hex hash per iteration to avoid dedup-path measurement.
auto hexIter = "0000000000000000000000000000000000000000000000000000000000000000" +
std::to_string(iter++);
auto hash = hexIter.substr(hexIter.size() - 64);
auto result = engine_->store(hash, data_);
if (!result) {
state.SkipWithError("store failed");
return;
}
benchmark::DoNotOptimize(result);
}
state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * state.range(0));
}
BENCHMARK_REGISTER_F(StorageFixture, Store)
->Arg(1024) // 1KB
->Arg(65536) // 64KB
->Arg(1048576); // 1MB
BENCHMARK_DEFINE_F(StorageFixture, Retrieve)(benchmark::State& state) {
// Data pre-stored in SetUp. Hash collision across size variants is
// acceptable: each variant creates its own engine with unique data/hash.
for (auto _ : state) {
auto result = engine_->retrieveRaw(hash_);
if (!result) {
state.SkipWithError("retrieveRaw failed");
return;
}
benchmark::DoNotOptimize(result);
}
state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * state.range(0));
}
BENCHMARK_REGISTER_F(StorageFixture, Retrieve)->Arg(1024)->Arg(65536)->Arg(1048576);
} // namespace
BENCHMARK_MAIN();