-
Notifications
You must be signed in to change notification settings - Fork 243
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Benchmark test for the persistent store
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
1 parent
9a8fcbf
commit 237853b
Showing
3 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |