Skip to content

Commit

Permalink
Benchmark test for the persistent store
Browse files Browse the repository at this point in the history
Summary:
This piece of code is to perform the benchmark test for the persistent store, including #reads/second, #writes/second and #create/destroy per second.

(10, 100, 1000, 10000) random (key, value) pairs are generated as inputs.

Three benchmark functions are included in the file PersistentStoreBenchmark.cpp, which are: BM_PersistentStoreWrite(.), BM_PersistentStoreLoad(.) and BM_PersistentStoreCreateDestroy(.).

Reviewed By: saifhhasan

Differential Revision: D15532375

fbshipit-source-id: 49526cb178ded7643cf5f70805256ed14b9a9205
  • Loading branch information
yunhongxu authored and facebook-github-bot committed Jun 13, 2019
1 parent 9a8fcbf commit 237853b
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 0 deletions.
48 changes: 48 additions & 0 deletions openr/config-store/PersistentStoreWrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "openr/config-store/PersistentStoreWrapper.h"

namespace openr {

PersistentStoreWrapper::PersistentStoreWrapper(
fbzmq::Context& context,
const unsigned long tid,
// persistent store DB saving backoffs
std::chrono::milliseconds saveInitialBackoff,
std::chrono::milliseconds saveMaxBackoff)
: inprocSocket(folly::sformat("1-{}", tid)),
filePath(folly::sformat("/tmp/aq_persistent_store_test_{}", tid)),
sockUrl(folly::sformat("inproc://aq_persistent_store_test_{}", tid)) {
VLOG(1) << "PersistentStoreWrapper: Creating PersistentStore.";
store_ = std::make_shared<PersistentStore>(
inprocSocket,
filePath,
PersistentStoreUrl{sockUrl},
context,
saveInitialBackoff,
saveMaxBackoff);
}

void
PersistentStoreWrapper::run() noexcept {
storeThread_ = std::thread([this]() { store_->run(); });
store_->waitUntilRunning();
}

void
PersistentStoreWrapper::stop() {
// Return immediately if not running
if (!store_->isRunning()) {
return;
}

// Destroy socket for communicating with kvstore
store_->stop();
storeThread_.join();
}
} // namespace openr
51 changes: 51 additions & 0 deletions openr/config-store/PersistentStoreWrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <openr/config-store/PersistentStore.h>

namespace openr {

class PersistentStoreWrapper {
public:
PersistentStoreWrapper(
fbzmq::Context& context,
const unsigned long tid,
// persistent store DB saving backoffs
std::chrono::milliseconds saveInitialBackoff =
Constants::kPersistentStoreInitialBackoff,
std::chrono::milliseconds saveMaxBackoff =
Constants::kPersistentStoreMaxBackoff);

// Destructor will try to save DB to disk before destroying the object
~PersistentStoreWrapper() {
stop();
}

/**
* Synchronous APIs to run and stop PersistentStore. This creates a thread
* and stop it on destruction.
*
* Synchronous => function call with return only after thread is
* running/stopped completely.
*/
void run() noexcept;
void stop();

public:
const std::string inprocSocket;
const std::string filePath;
const std::string sockUrl;

private:
std::shared_ptr<PersistentStore> store_;

// Thread in which PersistentStore will be running.
std::thread storeThread_;
};
} // namespace openr
132 changes: 132 additions & 0 deletions openr/config-store/tests/PersistentStoreBenchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include <benchmark/benchmark.h>
#include <folly/Random.h>
#include <openr/config-store/PersistentStoreClient.h>
#include <openr/config-store/PersistentStoreWrapper.h>

namespace {
// kIterations
uint32_t kIterations = 1000;
} // namespace

namespace openr {

std::vector<std::string>
constructRandomVector(uint32_t entryInStore) {
std::vector<std::string> stringKeys;
stringKeys.reserve(entryInStore);
for (auto i = 0; i < entryInStore; ++i) {
stringKeys.push_back(folly::sformat("key-{}", i));
}
return stringKeys;
}

static void
writeKeyValueToStore(
const std::vector<std::string>& stringKeys,
const std::unique_ptr<PersistentStoreClient>& client,
const uint32_t skipStep) {
for (auto index = 0; index < stringKeys.size(); index += skipStep) {
client
->store(
stringKeys[index],
folly::sformat("val-{}", folly::Random::rand32()))
.value();
}
}

static void
eraseKeyFromStore(
const std::vector<std::string>& stringKeys,
const std::unique_ptr<PersistentStoreClient>& client) {
for (auto stringKey : stringKeys) {
client->erase(stringKey).value();
}
}

static void
BM_PersistentStoreWrite(benchmark::State& state) {
fbzmq::Context context;
const auto tid = std::hash<std::thread::id>()(std::this_thread::get_id());

// Create new storeWrapper and perform some operations on it
auto storeWrapper = std::make_unique<PersistentStoreWrapper>(context, tid);
storeWrapper->run();
auto client = std::make_unique<PersistentStoreClient>(
PersistentStoreUrl{storeWrapper->sockUrl}, context);

// Generate keys
auto stringKeys = constructRandomVector(state.range(0));
writeKeyValueToStore(stringKeys, client, 1);
auto iterations =
(stringKeys.size() / kIterations == 0) ? stringKeys.size() : kIterations;

for (auto _ : state) {
// Write (key, random_value) pairs to store
writeKeyValueToStore(stringKeys, client, stringKeys.size() / iterations);
}

state.SetItemsProcessed(state.iterations() * iterations);

// Erase the keys and stop store before exiting
eraseKeyFromStore(stringKeys, client);
storeWrapper->stop();
}

BENCHMARK(BM_PersistentStoreWrite)->RangeMultiplier(10)->Range(10, 100);

static void
BM_PersistentStoreLoad(benchmark::State& state) {
fbzmq::Context context;
const auto tid = std::hash<std::thread::id>()(std::this_thread::get_id());
// Create new storeWrapper and perform some operations on it
auto storeWrapper = std::make_unique<PersistentStoreWrapper>(context, tid);
storeWrapper->run();
auto client = std::make_unique<PersistentStoreClient>(
PersistentStoreUrl{storeWrapper->sockUrl}, context);

// Generate keys
auto stringKeys = constructRandomVector(state.range(0));
writeKeyValueToStore(stringKeys, client, 1);
auto iterations =
(stringKeys.size() / kIterations == 0) ? stringKeys.size() : kIterations;

for (auto _ : state) {
// Load value by key from store
for (auto index = 0; index < stringKeys.size();
index += stringKeys.size() / iterations) {
client->load<std::string>(stringKeys[index]).value();
}
}

state.SetItemsProcessed(state.iterations() * iterations);
// Erase the keys and stop store before exiting
eraseKeyFromStore(stringKeys, client);
storeWrapper->stop();
}

BENCHMARK(BM_PersistentStoreLoad)->RangeMultiplier(100)->Range(10, 100);

static void
BM_PersistentStoreCreateDestroy(benchmark::State& state) {
fbzmq::Context context;

const auto tid = std::hash<std::thread::id>()(std::this_thread::get_id());

for (auto _ : state) {
// Create new storeWrapper and perform some operations on it
auto storeWrapper = std::make_unique<PersistentStoreWrapper>(context, tid);
}

state.SetItemsProcessed(state.iterations());
}

BENCHMARK(BM_PersistentStoreCreateDestroy);
} // namespace openr
BENCHMARK_MAIN();

0 comments on commit 237853b

Please sign in to comment.