Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3f963bb
global and local build config with profiling flags.
harish876 Nov 15, 2024
804dcd1
integrated basic memory hook for RSS calculation
harish876 Nov 15, 2024
b67fa88
edited script to generate callgraph using gprof
harish876 Nov 15, 2024
4404af5
enabling level db as default storage engine
harish876 Nov 15, 2024
33c16f2
systemd telegraf script to stream prometheus node_exporter data to In…
harish876 Nov 15, 2024
7c35fe8
added lmdb storage engine interface and partially implemented.
harish876 Nov 16, 2024
ccade23
bootstrapping script to run perf tools
harish876 Nov 30, 2024
c625f78
adding process exporter to bootstrapping script
harish876 Nov 30, 2024
e1ce45d
Added LRU Cache and Observabiity stats
harish876 Dec 9, 2024
676a5d3
Merge pull request #1 from harish876/memory-hooks-integration
harish876 Jan 12, 2025
491b254
lry cache controlled using settings
harish876 Feb 12, 2025
4adc82f
Merge branch 'apache:master' into master
harish876 Feb 12, 2025
7eb9fff
removing lmdb implementation
harish876 Feb 12, 2025
d8cbe16
removing unecessary scripts
harish876 Feb 12, 2025
71975f2
Resolving comments for build flags and memory leak
harish876 Feb 17, 2025
35ed786
resolved error. options.block_cache_ integration still not working
harish876 Feb 17, 2025
b9b3363
added UT's for TC's. removed logs from stats and changed lru implemen…
harish876 Feb 19, 2025
0d02a14
reverting configs and removing unwanted files
harish876 Feb 19, 2025
8348689
removing unwanted tst logs
harish876 Feb 19, 2025
0a85b15
refactor: rename GetMetrics to UpdateMetrics and improve cache handli…
harish876 Mar 7, 2025
ccb268d
feat: add LevelDB block cache support and corresponding tests.
harish876 Mar 7, 2025
4cd5b88
feat: enhance LevelDB block cache with configurable capacity and upda…
harish876 Mar 7, 2025
a642ef8
refactor: update transaction summary variable names for consistency
harish876 Mar 7, 2025
08203e3
build: optimize compilation flags by adding optimization level
harish876 Mar 7, 2025
94d2a72
build: remove debugging flags from kv_service and api_tools builds
harish876 Mar 14, 2025
a759dda
build: remove profiling flags from set_random_data binary
harish876 Mar 14, 2025
a0a136f
build: remove pyroscope monitoring from kv service startup script
harish876 Mar 15, 2025
32b5758
build: include string header in lru_cache implementation
harish876 Mar 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bazelrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
build --cxxopt='-std=c++17' --copt=-O3 --jobs=40
build --cxxopt='-std=c++17' --copt=-O3 --jobs=40
#build --action_env=PYTHON_BIN_PATH="/usr/bin/python3.10"
#build --action_env=PYTHON_LIB_PATH="/usr/include/python3.10"

7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ sdk_validator/venv
__pycache__
MODULE.*
apache_release
*.out.*
*.data.*
*.pb.*
.cache/
resdb/
100*_db/
gmon.out
16 changes: 16 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
workspace(name = "com_resdb_nexres")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "hedron_compile_commands",
#Replace the commit hash (4f28899228fb3ad0126897876f147ca15026151e) with the latest commit hash from the repo
url = "https://github.com/hedronvision/bazel-compile-commands-extractor/archive/4f28899228fb3ad0126897876f147ca15026151e.tar.gz",
strip_prefix = "bazel-compile-commands-extractor-4f28899228fb3ad0126897876f147ca15026151e",
)
load("@hedron_compile_commands//:workspace_setup.bzl", "hedron_compile_commands_setup")
hedron_compile_commands_setup()
load("@hedron_compile_commands//:workspace_setup_transitive.bzl", "hedron_compile_commands_setup_transitive")
hedron_compile_commands_setup_transitive()
load("@hedron_compile_commands//:workspace_setup_transitive_transitive.bzl", "hedron_compile_commands_setup_transitive_transitive")
hedron_compile_commands_setup_transitive_transitive()
load("@hedron_compile_commands//:workspace_setup_transitive_transitive_transitive.bzl", "hedron_compile_commands_setup_transitive_transitive_transitive")
hedron_compile_commands_setup_transitive_transitive_transitive()

load("//:repositories.bzl", "nexres_repositories")

nexres_repositories()
Expand Down
16 changes: 16 additions & 0 deletions chain/storage/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ cc_library(
"//chain/storage/proto:kv_cc_proto",
"//chain/storage/proto:leveldb_config_cc_proto",
"//common:comm",
"//common/lru:lru_cache",
"//platform/statistic:stats",
"//third_party:leveldb",
],
)
Expand All @@ -64,4 +66,18 @@ cc_test(
":memory_db",
"//common/test:test_main",
],
timeout = "short", # Set the timeout to "short"
size = "small", # Set the size to "small"
)

cc_test(
name = "leveldb_test",
srcs = ["leveldb_test.cpp"],
deps = [
":leveldb",
"//platform/statistic:stats",
"//common/test:test_main",
],
timeout = "short", # Set the timeout to "short"
size = "small", # Set the size to "small"
)
21 changes: 16 additions & 5 deletions chain/storage/kv_storage_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ namespace resdb {
namespace storage {
namespace {

enum StorageType {
MEM = 0,
LEVELDB = 1,
};
enum StorageType { MEM = 0, LEVELDB = 1, LEVELDB_WITH_BLOCK_CACHE = 2 };

class KVStorageTest : public ::testing::TestWithParam<StorageType> {
protected:
Expand All @@ -47,6 +44,12 @@ class KVStorageTest : public ::testing::TestWithParam<StorageType> {
Reset();
storage = NewResLevelDB(path_);
break;
case LEVELDB_WITH_BLOCK_CACHE:
Reset();
LevelDBInfo config;
config.set_enable_block_cache(true);
storage = NewResLevelDB(path_, config);
break;
}
}

Expand Down Expand Up @@ -218,8 +221,16 @@ TEST_P(KVStorageTest, GetHistory) {
}
}

TEST_P(KVStorageTest, BlockCacheSpecificTest) {
if (GetParam() == LEVELDB_WITH_BLOCK_CACHE) {
std::cout << "Running BlockCacheSpecificTest for LEVELDB_WITH_BLOCK_CACHE"
<< std::endl;
}
}

INSTANTIATE_TEST_CASE_P(KVStorageTest, KVStorageTest,
::testing::Values(MEM, LEVELDB));
::testing::Values(MEM, LEVELDB,
LEVELDB_WITH_BLOCK_CACHE));

} // namespace
} // namespace storage
Expand Down
56 changes: 50 additions & 6 deletions chain/storage/leveldb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@
#include "chain/storage/leveldb.h"

#include <glog/logging.h>
#include <unistd.h>

#include <cstdint>

#include "chain/storage/proto/kv.pb.h"
#include "leveldb/options.h"

namespace resdb {
namespace storage {
Expand Down Expand Up @@ -50,6 +54,16 @@ ResLevelDB::ResLevelDB(std::optional<LevelDBInfo> config) {
path = (*config).path();
}
}
if ((*config).enable_block_cache()) {
uint32_t capacity = 1000;
if ((*config).has_block_cache_capacity()) {
capacity = (*config).block_cache_capacity();
}
block_cache_ =
std::make_unique<LRUCache<std::string, std::string>>(capacity);
LOG(ERROR) << "initialized block cache" << std::endl;
}
global_stats_ = Stats::GetGlobalStats();
CreateDB(path);
}

Expand All @@ -74,15 +88,22 @@ ResLevelDB::~ResLevelDB() {
if (db_) {
db_.reset();
}
if (block_cache_) {
block_cache_->Flush();
}
}

int ResLevelDB::SetValue(const std::string& key, const std::string& value) {
if (block_cache_) {
block_cache_->Put(key, value);
}
batch_.Put(key, value);

if (batch_.ApproximateSize() >= write_batch_size_) {
leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch_);
if (status.ok()) {
batch_.Clear();
UpdateMetrics();
return 0;
} else {
LOG(ERROR) << "flush buffer fail:" << status.ToString();
Expand All @@ -93,13 +114,23 @@ int ResLevelDB::SetValue(const std::string& key, const std::string& value) {
}

std::string ResLevelDB::GetValue(const std::string& key) {
std::string value = "";
leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value);
if (status.ok()) {
return value;
} else {
return "";
std::string value;
bool found_in_cache = false;

if (block_cache_) {
value = block_cache_->Get(key);
found_in_cache = !value.empty();
}

if (!found_in_cache) {
leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value);
if (!status.ok()) {
value.clear(); // Ensure value is empty if not found in DB
}
}

UpdateMetrics();
return value;
}

std::string ResLevelDB::GetAllValues(void) {
Expand Down Expand Up @@ -134,6 +165,19 @@ std::string ResLevelDB::GetRange(const std::string& min_key,
return values;
}

bool ResLevelDB::UpdateMetrics() {
if (block_cache_ == nullptr) {
return false;
}
std::string stats;
std::string approximate_size;
db_->GetProperty("leveldb.stats", &stats);
db_->GetProperty("leveldb.approximate-memory-usage", &approximate_size);
global_stats_->SetStorageEngineMetrics(block_cache_->GetCacheHitRatio(),
stats, approximate_size);
return true;
}

bool ResLevelDB::Flush() {
leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch_);
if (status.ok()) {
Expand Down
8 changes: 8 additions & 0 deletions chain/storage/leveldb.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@

#include "chain/storage/proto/leveldb_config.pb.h"
#include "chain/storage/storage.h"
#include "common/lru/lru_cache.h"
#include "leveldb/db.h"
#include "leveldb/write_batch.h"
#include "platform/statistic/stats.h"

namespace resdb {
namespace storage {
Expand Down Expand Up @@ -65,6 +67,8 @@ class ResLevelDB : public Storage {
std::vector<std::pair<std::string, int>> GetTopHistory(
const std::string& key, int top_number) override;

bool UpdateMetrics();

bool Flush() override;

private:
Expand All @@ -75,6 +79,10 @@ class ResLevelDB : public Storage {
::leveldb::WriteBatch batch_;
unsigned int write_buffer_size_ = 64 << 20;
unsigned int write_batch_size_ = 1;

protected:
Stats* global_stats_ = nullptr;
std::unique_ptr<LRUCache<std::string, std::string>> block_cache_;
};

} // namespace storage
Expand Down
117 changes: 117 additions & 0 deletions chain/storage/leveldb_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#include "chain/storage/leveldb.h"

#include <glog/logging.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <filesystem>

namespace resdb {
namespace storage {
namespace {

enum class CacheConfig { DISABLED, ENABLED };

class TestableResLevelDB : public ResLevelDB {
public:
using ResLevelDB::block_cache_;
using ResLevelDB::global_stats_;
using ResLevelDB::ResLevelDB;
};

class LevelDBTest : public ::testing::TestWithParam<CacheConfig> {
protected:
LevelDBTest() {
LevelDBInfo config;
if (GetParam() == CacheConfig::ENABLED) {
config.set_enable_block_cache(true);
config.set_block_cache_capacity(1000);
} else {
Reset();
}
storage = std::make_unique<TestableResLevelDB>(config);
}

protected:
std::unique_ptr<TestableResLevelDB> storage;
std::string path_ = "/tmp/leveldb_test";

private:
void Reset() { std::filesystem::remove_all(path_.c_str()); }
};

TEST_P(LevelDBTest, BlockCacheEnabled) {
if (GetParam() == CacheConfig::ENABLED) {
EXPECT_TRUE(storage->block_cache_ != nullptr);
EXPECT_TRUE(storage->block_cache_->GetCapacity() == 1000);
} else {
EXPECT_TRUE(storage->block_cache_ == nullptr);
EXPECT_FALSE(storage->UpdateMetrics());
}
}

TEST_P(LevelDBTest, AddValueAndCheckCache) {
if (GetParam() == CacheConfig::ENABLED) {
// Add a value
std::string key = "test_key";
std::string value = "test_value";
EXPECT_EQ(storage->SetValue(key, value), 0);

// Check if CacheHit is incremented in the Stats class
EXPECT_TRUE(storage->block_cache_->Get(key) == "test_value");
EXPECT_EQ(storage->block_cache_->GetCacheHits(), 1);
}
}

TEST_P(LevelDBTest, CacheEvictionPolicy) {
if (GetParam() == CacheConfig::ENABLED) {
// Insert 1000 values
for (int i = 1; i <= 1000; ++i) {
std::string key = "key_" + std::to_string(i);
std::string value = "value_" + std::to_string(i);
EXPECT_EQ(storage->SetValue(key, value), 0);
}

// Insert the 1001st value
std::string key_1001 = "key_1001";
std::string value_1001 = "value_1001";
EXPECT_EQ(storage->SetValue(key_1001, value_1001), 0);

// Check that the 1001st value is not present in the cache
EXPECT_TRUE(storage->GetValue("key_1") == "value_1");
EXPECT_EQ(storage->block_cache_->GetCacheMisses(), 1);

// Expect key_2 to be present in cache and hence a cache hit
EXPECT_TRUE(storage->GetValue("key_2") == "value_2");
EXPECT_EQ(storage->block_cache_->GetCacheHits(), 1);

EXPECT_TRUE(storage->UpdateMetrics());
}
}

INSTANTIATE_TEST_CASE_P(LevelDBTest, LevelDBTest,
::testing::Values(CacheConfig::ENABLED,
CacheConfig::DISABLED));

} // namespace
} // namespace storage
} // namespace resdb
2 changes: 2 additions & 0 deletions chain/storage/proto/leveldb_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ message LevelDBInfo {
uint32 write_buffer_size_mb = 2;
uint32 write_batch_size = 3;
string path = 4;
optional bool enable_block_cache = 5;
optional uint32 block_cache_capacity = 6;
}
Loading