Optimizations: RocksDB perf optimizations
This commit is contained in:
parent
796fe44c99
commit
fdd5b132e2
@ -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());
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user