Optimizations: RocksDB perf optimizations

This commit is contained in:
Andreja Tonev 2024-03-13 14:15:28 +01:00
parent 796fe44c99
commit fdd5b132e2
7 changed files with 57 additions and 20 deletions

View File

@ -36,6 +36,19 @@ KVStore::KVStore(std::filesystem::path storage) : pimpl_(std::make_unique<impl>(
pimpl_->db.reset(db); pimpl_->db.reset(db);
} }
KVStore::KVStore(std::filesystem::path storage, rocksdb::Options db_options) : pimpl_(std::make_unique<impl>()) {
pimpl_->storage = storage;
pimpl_->options = std::move(db_options);
if (!utils::EnsureDir(pimpl_->storage))
throw KVStoreError("Folder for the key-value store " + pimpl_->storage.string() + " couldn't be initialized!");
rocksdb::DB *db = nullptr;
auto s = rocksdb::DB::Open(pimpl_->options, storage.c_str(), &db);
if (!s.ok())
throw KVStoreError("RocksDB couldn't be initialized inside " + storage.string() + " -- " +
std::string(s.ToString()));
pimpl_->db.reset(db);
}
KVStore::~KVStore() { KVStore::~KVStore() {
if (pimpl_ == nullptr) return; if (pimpl_ == nullptr) return;
spdlog::debug("Destroying KVStore at {}", pimpl_->storage.string()); spdlog::debug("Destroying KVStore at {}", pimpl_->storage.string());

View File

@ -11,6 +11,7 @@
#pragma once #pragma once
#include <rocksdb/options.h>
#include <filesystem> #include <filesystem>
#include <map> #include <map>
#include <memory> #include <memory>
@ -43,6 +44,7 @@ class KVStore final {
* storage directory because that will lead to undefined behaviour. * storage directory because that will lead to undefined behaviour.
*/ */
explicit KVStore(std::filesystem::path storage); explicit KVStore(std::filesystem::path storage);
explicit KVStore(std::filesystem::path storage, rocksdb::Options db_options);
KVStore(const KVStore &other) = delete; KVStore(const KVStore &other) = delete;
KVStore(KVStore &&other); KVStore(KVStore &&other);

View File

@ -42,6 +42,7 @@
#include "storage/v2/durability/durability.hpp" #include "storage/v2/durability/durability.hpp"
#include "system/system.hpp" #include "system/system.hpp"
#include "telemetry/telemetry.hpp" #include "telemetry/telemetry.hpp"
#include "utils/on_scope_exit.hpp"
#include "utils/signals.hpp" #include "utils/signals.hpp"
#include "utils/sysinfo/memory.hpp" #include "utils/sysinfo/memory.hpp"
#include "utils/system_info.hpp" #include "utils/system_info.hpp"
@ -145,6 +146,8 @@ int main(int argc, char **argv) {
// Unhandled exception handler init. // Unhandled exception handler init.
std::set_terminate(&memgraph::utils::TerminateHandler); std::set_terminate(&memgraph::utils::TerminateHandler);
memgraph::utils::OnScopeExit deinit_pds([]() { memgraph::storage::PDS::Deinit(); });
// Initialize Python // Initialize Python
auto *program_name = Py_DecodeLocale(argv[0], nullptr); auto *program_name = Py_DecodeLocale(argv[0], nullptr);
MG_ASSERT(program_name); MG_ASSERT(program_name);

View File

@ -52,6 +52,9 @@ struct Edge {
bool deleted; bool deleted;
// uint8_t PAD; // uint8_t PAD;
// uint16_t PAD; // uint16_t PAD;
bool has_prop;
class HotFixMove { class HotFixMove {
public: public:
HotFixMove() {} HotFixMove() {}
@ -77,20 +80,19 @@ struct Edge {
Gid HotFixForGID() const { return Gid::FromUint(gid.AsUint() + (1 << 31)); } Gid HotFixForGID() const { return Gid::FromUint(gid.AsUint() + (1 << 31)); }
PropertyValue GetProperty(PropertyId property) const { PropertyValue GetProperty(PropertyId property) const {
if (deleted) return {}; if (!has_prop) return {};
const auto prop = PDS::get()->Get(HotFixForGID(), property); const auto prop = PDS::get()->Get(HotFixForGID(), property);
if (prop) return *prop; if (prop) return *prop;
return {}; return {};
} }
bool SetProperty(PropertyId property, const PropertyValue &value) { bool SetProperty(PropertyId property, const PropertyValue &value) {
if (deleted) return {}; if (!has_prop) return {};
return PDS::get()->Set(HotFixForGID(), property, value); return PDS::get()->Set(HotFixForGID(), property, value);
} }
template <typename TContainer> template <typename TContainer>
bool InitProperties(const TContainer &properties) { bool InitProperties(const TContainer &properties) {
if (deleted) return {};
auto *pds = PDS::get(); auto *pds = PDS::get();
for (const auto &[property, value] : properties) { for (const auto &[property, value] : properties) {
if (value.IsNull()) { if (value.IsNull()) {
@ -99,23 +101,26 @@ struct Edge {
if (!pds->Set(HotFixForGID(), property, value)) { if (!pds->Set(HotFixForGID(), property, value)) {
return false; return false;
} }
has_prop = true;
} }
return true; return true;
} }
void ClearProperties() { void ClearProperties() {
if (!has_prop) return;
has_prop = false;
auto *pds = PDS::get(); auto *pds = PDS::get();
pds->Clear(HotFixForGID()); pds->Clear(HotFixForGID());
} }
std::map<PropertyId, PropertyValue> Properties() { std::map<PropertyId, PropertyValue> Properties() {
if (deleted) return {}; if (!has_prop) return {};
return PDS::get()->Get(HotFixForGID()); return PDS::get()->Get(HotFixForGID());
} }
std::vector<std::tuple<PropertyId, PropertyValue, PropertyValue>> UpdateProperties( std::vector<std::tuple<PropertyId, PropertyValue, PropertyValue>> UpdateProperties(
std::map<PropertyId, PropertyValue> &properties) { std::map<PropertyId, PropertyValue> &properties) {
if (deleted) return {}; if (!has_prop && properties.empty()) return {};
auto old_properties = Properties(); auto old_properties = Properties();
ClearProperties(); ClearProperties();
@ -140,7 +145,7 @@ struct Edge {
} }
uint64_t PropertySize(PropertyId property) const { uint64_t PropertySize(PropertyId property) const {
if (deleted) return {}; if (!has_prop) return {};
return PDS::get()->GetSize(HotFixForGID(), property); return PDS::get()->GetSize(HotFixForGID(), property);
} }
}; };

View File

@ -11,22 +11,32 @@
#include "storage/v2/property_disk_store.hpp" #include "storage/v2/property_disk_store.hpp"
#include <cstdint> #include <rocksdb/filter_policy.h>
#include <cstring> #include <rocksdb/memtablerep.h>
#include <iterator> #include <rocksdb/options.h>
#include <limits> #include <rocksdb/slice_transform.h>
#include <optional> #include <rocksdb/statistics.h>
#include <sstream> #include <rocksdb/table.h>
#include <tuple>
#include <type_traits>
#include <utility>
#include "storage/v2/temporal.hpp"
#include "utils/cast.hpp"
#include "utils/logging.hpp"
namespace memgraph::storage { namespace memgraph::storage {
PDS *PDS::ptr_ = nullptr; PDS *PDS::ptr_ = nullptr;
PDS::PDS(std::filesystem::path root)
: kvstore_{root / "pds", std::invoke([]() {
rocksdb::Options options;
rocksdb::BlockBasedTableOptions table_options;
table_options.block_cache = rocksdb::NewLRUCache(128 * 1024 * 1024);
table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(sizeof(storage::Gid)));
options.table_factory.reset(rocksdb::NewBlockBasedTableFactory(table_options));
options.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(sizeof(storage::Gid)));
options.max_background_jobs = 4;
options.enable_pipelined_write = true;
options.avoid_unnecessary_blocking_io = true;
options.create_if_missing = true;
return options;
})} {}
} // namespace memgraph::storage } // namespace memgraph::storage

View File

@ -11,6 +11,7 @@
#pragma once #pragma once
#include <rocksdb/options.h>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <json/json.hpp> #include <json/json.hpp>
@ -34,6 +35,8 @@ class PDS {
if (ptr_ == nullptr) ptr_ = new PDS(root); if (ptr_ == nullptr) ptr_ = new PDS(root);
} }
static void Deinit() { delete ptr_; }
static PDS *get() { static PDS *get() {
if (ptr_ == nullptr) { if (ptr_ == nullptr) {
ptr_ = new PDS("/tmp"); ptr_ = new PDS("/tmp");
@ -126,7 +129,7 @@ class PDS {
// kvstore::KVStore::iterator Itr() {} // kvstore::KVStore::iterator Itr() {}
private: private:
PDS(std::filesystem::path root) : kvstore_{root / "pds"} {} PDS(std::filesystem::path root);
kvstore::KVStore kvstore_; kvstore::KVStore kvstore_;
static PDS *ptr_; static PDS *ptr_;
}; };

View File

@ -130,6 +130,7 @@ struct Vertex {
void ClearProperties() { void ClearProperties() {
if (!has_prop) return; if (!has_prop) return;
has_prop = false;
auto *pds = PDS::get(); auto *pds = PDS::get();
pds->Clear(gid); pds->Clear(gid);
} }