Optimizations: RocksDB perf optimizations

This commit is contained in:
Andreja Tonev 2024-03-13 14:15:28 +01:00
parent 0215edb4bf
commit 39e1776a74
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);
}
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() {
if (pimpl_ == nullptr) return;
spdlog::debug("Destroying KVStore at {}", pimpl_->storage.string());

View File

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

View File

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

View File

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

View File

@ -11,22 +11,32 @@
#include "storage/v2/property_disk_store.hpp"
#include <cstdint>
#include <cstring>
#include <iterator>
#include <limits>
#include <optional>
#include <sstream>
#include <tuple>
#include <type_traits>
#include <utility>
#include "storage/v2/temporal.hpp"
#include "utils/cast.hpp"
#include "utils/logging.hpp"
#include <rocksdb/filter_policy.h>
#include <rocksdb/memtablerep.h>
#include <rocksdb/options.h>
#include <rocksdb/slice_transform.h>
#include <rocksdb/statistics.h>
#include <rocksdb/table.h>
namespace memgraph::storage {
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

View File

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

View File

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