mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Persistent optimization (#382)
* State serialization consuming less RAM * Move large-boc-serializer to crypto/vm, refactor code Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
parent
c04eb8e4f3
commit
89b8717cf8
21 changed files with 665 additions and 157 deletions
|
@ -102,6 +102,10 @@ void CellDbIn::store_cell(BlockIdExt block_id, td::Ref<vm::Cell> cell, td::Promi
|
|||
promise.set_result(boc_->load_cell(cell->get_hash().as_slice()));
|
||||
}
|
||||
|
||||
void CellDbIn::get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) {
|
||||
promise.set_result(boc_->get_cell_db_reader());
|
||||
}
|
||||
|
||||
void CellDbIn::alarm() {
|
||||
auto R = get_block(last_gc_);
|
||||
R.ensure();
|
||||
|
@ -264,6 +268,10 @@ void CellDb::store_cell(BlockIdExt block_id, td::Ref<vm::Cell> cell, td::Promise
|
|||
td::actor::send_closure(cell_db_, &CellDbIn::store_cell, block_id, std::move(cell), std::move(promise));
|
||||
}
|
||||
|
||||
void CellDb::get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) {
|
||||
td::actor::send_closure(cell_db_, &CellDbIn::get_cell_db_reader, std::move(promise));
|
||||
}
|
||||
|
||||
void CellDb::start_up() {
|
||||
boc_ = vm::DynamicBagOfCellsDb::create();
|
||||
cell_db_ = td::actor::create_actor<CellDbIn>("celldbin", root_db_, actor_id(this), path_);
|
||||
|
|
|
@ -40,6 +40,7 @@ class CellDbIn : public td::actor::Actor {
|
|||
|
||||
void load_cell(RootHash hash, td::Promise<td::Ref<vm::DataCell>> promise);
|
||||
void store_cell(BlockIdExt block_id, td::Ref<vm::Cell> cell, td::Promise<td::Ref<vm::DataCell>> promise);
|
||||
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise);
|
||||
|
||||
CellDbIn(td::actor::ActorId<RootDb> root_db, td::actor::ActorId<CellDb> parent, std::string path);
|
||||
|
||||
|
@ -96,6 +97,7 @@ class CellDb : public td::actor::Actor {
|
|||
started_ = true;
|
||||
boc_->set_loader(std::make_unique<vm::CellLoader>(std::move(snapshot))).ensure();
|
||||
}
|
||||
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise);
|
||||
|
||||
CellDb(td::actor::ActorId<RootDb> root_db, std::string path) : root_db_(root_db), path_(path) {
|
||||
}
|
||||
|
|
|
@ -270,6 +270,10 @@ void RootDb::get_block_state(ConstBlockHandle handle, td::Promise<td::Ref<ShardS
|
|||
}
|
||||
}
|
||||
|
||||
void RootDb::get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) {
|
||||
td::actor::send_closure(cell_db_, &CellDb::get_cell_db_reader, std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::BufferSlice state,
|
||||
td::Promise<td::Unit> promise) {
|
||||
td::actor::send_closure(archive_db_, &ArchiveManager::add_persistent_state, block_id, masterchain_block_id,
|
||||
|
|
|
@ -60,6 +60,7 @@ class RootDb : public Db {
|
|||
void store_block_state(BlockHandle handle, td::Ref<ShardState> state,
|
||||
td::Promise<td::Ref<ShardState>> promise) override;
|
||||
void get_block_state(ConstBlockHandle handle, td::Promise<td::Ref<ShardState>> promise) override;
|
||||
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) override;
|
||||
|
||||
void store_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) override;
|
||||
void get_block_handle(BlockIdExt id, td::Promise<BlockHandle> promise) override;
|
||||
|
|
|
@ -50,6 +50,7 @@ class Db : public td::actor::Actor {
|
|||
virtual void store_block_state(BlockHandle handle, td::Ref<ShardState> state,
|
||||
td::Promise<td::Ref<ShardState>> promise) = 0;
|
||||
virtual void get_block_state(ConstBlockHandle handle, td::Promise<td::Ref<ShardState>> promise) = 0;
|
||||
virtual void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) = 0;
|
||||
|
||||
virtual void store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::BufferSlice state,
|
||||
td::Promise<td::Unit> promise) = 0;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "message-queue.h"
|
||||
#include "validator/validator.h"
|
||||
#include "liteserver.h"
|
||||
#include "crypto/vm/db/DynamicBagOfCellsDb.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -55,6 +56,7 @@ class ValidatorManager : public ValidatorManagerInterface {
|
|||
public:
|
||||
virtual void set_block_state(BlockHandle handle, td::Ref<ShardState> state,
|
||||
td::Promise<td::Ref<ShardState>> promise) = 0;
|
||||
virtual void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) = 0;
|
||||
virtual void store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::BufferSlice state,
|
||||
td::Promise<td::Unit> promise) = 0;
|
||||
virtual void store_persistent_state_file_gen(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
|
|
|
@ -674,6 +674,10 @@ void ValidatorManagerImpl::set_block_state(BlockHandle handle, td::Ref<ShardStat
|
|||
td::actor::send_closure(db_, &Db::store_block_state, handle, state, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_cell_db_reader, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
td::BufferSlice state, td::Promise<td::Unit> promise) {
|
||||
td::actor::send_closure(db_, &Db::store_persistent_state_file, block_id, masterchain_block_id, std::move(state),
|
||||
|
|
|
@ -141,6 +141,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
|
||||
void set_block_state(BlockHandle handle, td::Ref<ShardState> state,
|
||||
td::Promise<td::Ref<ShardState>> promise) override;
|
||||
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) override;
|
||||
void store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::BufferSlice state,
|
||||
td::Promise<td::Unit> promise) override;
|
||||
void store_persistent_state_file_gen(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
|
|
|
@ -530,6 +530,10 @@ void ValidatorManagerImpl::get_block_handle(BlockIdExt id, bool force, td::Promi
|
|||
td::actor::send_closure(db_, &Db::get_block_handle, id, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_cell_db_reader, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::register_block_handle(BlockHandle handle, td::Promise<BlockHandle> promise) {
|
||||
auto it = handles_.find(handle->id());
|
||||
if (it != handles_.end()) {
|
||||
|
|
|
@ -165,6 +165,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
td::Promise<td::Ref<ShardState>> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) override;
|
||||
void store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::BufferSlice state,
|
||||
td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -1045,6 +1045,10 @@ void ValidatorManagerImpl::set_block_state(BlockHandle handle, td::Ref<ShardStat
|
|||
td::actor::send_closure(db_, &Db::store_block_state, handle, state, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_cell_db_reader, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
td::BufferSlice state, td::Promise<td::Unit> promise) {
|
||||
td::actor::send_closure(db_, &Db::store_persistent_state_file, block_id, masterchain_block_id, std::move(state),
|
||||
|
|
|
@ -345,6 +345,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
|
||||
void set_block_state(BlockHandle handle, td::Ref<ShardState> state,
|
||||
td::Promise<td::Ref<ShardState>> promise) override;
|
||||
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) override;
|
||||
void store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::BufferSlice state,
|
||||
td::Promise<td::Unit> promise) override;
|
||||
void store_persistent_state_file_gen(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
|
|
|
@ -82,24 +82,24 @@ void AsyncStateSerializer::alarm() {
|
|||
}
|
||||
|
||||
void AsyncStateSerializer::request_masterchain_state() {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &AsyncStateSerializer::fail_handler,
|
||||
R.move_as_error_prefix("failed to get masterchain state: "));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &AsyncStateSerializer::got_masterchain_state,
|
||||
td::Ref<MasterchainState>(R.move_as_ok()));
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_state_from_db, masterchain_handle_, std::move(P));
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &AsyncStateSerializer::fail_handler,
|
||||
R.move_as_error_prefix("failed to get masterchain state: "));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &AsyncStateSerializer::got_masterchain_state,
|
||||
td::Ref<MasterchainState>(R.move_as_ok()));
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_state_from_db, masterchain_handle_, std::move(P));
|
||||
}
|
||||
|
||||
void AsyncStateSerializer::request_shard_state(BlockIdExt shard) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &AsyncStateSerializer::got_shard_handle, R.move_as_ok());
|
||||
});
|
||||
return td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, shard, true, std::move(P));
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &AsyncStateSerializer::got_shard_handle, R.move_as_ok());
|
||||
});
|
||||
return td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, shard, true, std::move(P));
|
||||
}
|
||||
|
||||
void AsyncStateSerializer::next_iteration() {
|
||||
|
@ -122,8 +122,21 @@ void AsyncStateSerializer::next_iteration() {
|
|||
CHECK(masterchain_handle_->id() == last_block_id_);
|
||||
if (attempt_ < max_attempt() && last_key_block_id_.id.seqno < last_block_id_.id.seqno &&
|
||||
need_serialize(masterchain_handle_)) {
|
||||
if (!cell_db_reader_) {
|
||||
running_ = true;
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::shared_ptr<vm::CellDbReader>> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &AsyncStateSerializer::fail_handler,
|
||||
R.move_as_error_prefix("failed to get cell db reader: "));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &AsyncStateSerializer::got_cell_db_reader, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_cell_db_reader, std::move(P));
|
||||
return;
|
||||
}
|
||||
if (!have_masterchain_state_) {
|
||||
LOG(INFO) << "started serializing persistent state for " << masterchain_handle_->id().seqno();
|
||||
LOG(INFO) << "started serializing persistent state for " << masterchain_handle_->id().id;
|
||||
// block next attempts immediately, but send actual request later
|
||||
running_ = true;
|
||||
delay_action(
|
||||
|
@ -143,9 +156,10 @@ void AsyncStateSerializer::next_iteration() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
LOG(INFO) << "finished serializing persistent state for " << masterchain_handle_->id().seqno();
|
||||
LOG(INFO) << "finished serializing persistent state for " << masterchain_handle_->id().id;
|
||||
last_key_block_ts_ = masterchain_handle_->unix_time();
|
||||
last_key_block_id_ = masterchain_handle_->id();
|
||||
cell_db_reader_ = nullptr;
|
||||
}
|
||||
if (!saved_to_db_) {
|
||||
running_ = true;
|
||||
|
@ -175,6 +189,13 @@ void AsyncStateSerializer::got_top_masterchain_handle(BlockIdExt block_id) {
|
|||
}
|
||||
}
|
||||
|
||||
void AsyncStateSerializer::got_cell_db_reader(std::shared_ptr<vm::CellDbReader> cell_db_reader) {
|
||||
cell_db_reader_ = std::move(cell_db_reader);
|
||||
running_ = false;
|
||||
attempt_ = 0;
|
||||
next_iteration();
|
||||
}
|
||||
|
||||
void AsyncStateSerializer::got_masterchain_handle(BlockHandle handle) {
|
||||
CHECK(!masterchain_handle_);
|
||||
masterchain_handle_ = std::move(handle);
|
||||
|
@ -184,7 +205,7 @@ void AsyncStateSerializer::got_masterchain_handle(BlockHandle handle) {
|
|||
}
|
||||
|
||||
void AsyncStateSerializer::got_masterchain_state(td::Ref<MasterchainState> state) {
|
||||
LOG(INFO) << "serializing masterchain state " << masterchain_handle_->id().seqno();
|
||||
LOG(INFO) << "serializing masterchain state " << masterchain_handle_->id().id;
|
||||
have_masterchain_state_ = true;
|
||||
CHECK(next_idx_ == 0);
|
||||
CHECK(shards_.size() == 0);
|
||||
|
@ -194,8 +215,8 @@ void AsyncStateSerializer::got_masterchain_state(td::Ref<MasterchainState> state
|
|||
shards_.push_back(v->top_block_id());
|
||||
}
|
||||
|
||||
auto write_data = [state] (td::FileFd& fd) {
|
||||
return state->serialize_to_file(fd);
|
||||
auto write_data = [hash = state->root_cell()->get_hash(), cell_db_reader = cell_db_reader_] (td::FileFd& fd) {
|
||||
return vm::std_boc_serialize_to_file_large(cell_db_reader, hash, fd, 31);
|
||||
};
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
|
@ -207,7 +228,7 @@ void AsyncStateSerializer::got_masterchain_state(td::Ref<MasterchainState> state
|
|||
}
|
||||
|
||||
void AsyncStateSerializer::stored_masterchain_state() {
|
||||
LOG(INFO) << "finished serializing masterchain state " << masterchain_handle_->id().seqno();
|
||||
LOG(INFO) << "finished serializing masterchain state " << masterchain_handle_->id().id;
|
||||
running_ = false;
|
||||
next_iteration();
|
||||
}
|
||||
|
@ -225,13 +246,13 @@ void AsyncStateSerializer::got_shard_handle(BlockHandle handle) {
|
|||
}
|
||||
|
||||
void AsyncStateSerializer::got_shard_state(BlockHandle handle, td::Ref<ShardState> state) {
|
||||
LOG(INFO) << "serializing shard state " << handle->id().seqno();
|
||||
auto write_data = [state] (td::FileFd& fd) {
|
||||
return state->serialize_to_file(fd);
|
||||
LOG(INFO) << "serializing shard state " << handle->id().id;
|
||||
auto write_data = [hash = state->root_cell()->get_hash(), cell_db_reader = cell_db_reader_] (td::FileFd& fd) {
|
||||
return vm::std_boc_serialize_to_file_large(cell_db_reader, hash, fd, 31);
|
||||
};
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
LOG(INFO) << "finished serializing shard state " << handle->id().seqno();
|
||||
LOG(INFO) << "finished serializing shard state " << handle->id().id;
|
||||
td::actor::send_closure(SelfId, &AsyncStateSerializer::success_handler);
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::store_persistent_state_file_gen, handle->id(),
|
||||
|
|
|
@ -42,6 +42,7 @@ class AsyncStateSerializer : public td::actor::Actor {
|
|||
|
||||
td::uint32 next_idx_ = 0;
|
||||
|
||||
std::shared_ptr<vm::CellDbReader> cell_db_reader_ = nullptr;
|
||||
BlockHandle masterchain_handle_;
|
||||
bool have_masterchain_state_ = false;
|
||||
|
||||
|
@ -70,6 +71,7 @@ class AsyncStateSerializer : public td::actor::Actor {
|
|||
|
||||
void next_iteration();
|
||||
void got_top_masterchain_handle(BlockIdExt block_id);
|
||||
void got_cell_db_reader(std::shared_ptr<vm::CellDbReader> cell_db_reader);
|
||||
void got_masterchain_handle(BlockHandle handle_);
|
||||
void got_masterchain_state(td::Ref<MasterchainState> state);
|
||||
void stored_masterchain_state();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue