Skip to content

Commit

Permalink
Merge pull request #1691 from AntelopeIO/gh_1650
Browse files Browse the repository at this point in the history
Improve chainbase mapped and heap behavior
  • Loading branch information
greg7mdp authored Oct 5, 2023
2 parents 42cf4b0 + d8fb38c commit 2a0e9c9
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 12 deletions.
8 changes: 6 additions & 2 deletions docs/01_nodeos/03_plugins/chain_plugin/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,14 @@ Config Options for eosio::chain_plugin:
headers signed by it will be fully
validated, but transactions in those
validated blocks will be trusted.
--database-map-mode arg (=mapped) Database map mode ("mapped", "heap", or
"locked").
--database-map-mode arg (=mapped) Database map mode ("mapped",
"mapped_private", "heap", or "locked").
In "mapped" mode database is memory
mapped as a file.
In "mapped_private" mode database is
memory mapped as a file using a private
mapping (no disk writeback until
program exit).
In "heap" mode database is preloaded in
to swappable memory and will use huge
pages if available.
Expand Down
26 changes: 19 additions & 7 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#include <new>
#include <shared_mutex>
#include <utility>

namespace eosio { namespace chain {

Expand Down Expand Up @@ -591,6 +592,7 @@ struct controller_impl {
EOS_ASSERT( snapshot, snapshot_exception, "No snapshot reader provided" );
this->shutdown = shutdown;
try {
auto snapshot_load_start_time = fc::time_point::now();
snapshot->validate();
if( auto blog_head = blog.head() ) {
ilog( "Starting initialization from snapshot and block log ${b}-${e}, this may take a significant amount of time",
Expand All @@ -606,8 +608,11 @@ struct controller_impl {
}
ilog( "Snapshot loaded, lib: ${lib}", ("lib", head->block_num) );

init(check_shutdown);
ilog( "Finished initialization from snapshot" );
init(std::move(check_shutdown));
if (conf.revert_to_private_mode)
db.revert_to_private_mode();
auto snapshot_load_time = (fc::time_point::now() - snapshot_load_start_time).to_seconds();
ilog( "Finished initialization from snapshot (snapshot load time was ${t}s)", ("t", snapshot_load_time) );
} catch (boost::interprocess::bad_alloc& e) {
elog( "Failed initialization from snapshot - db storage not configured to have enough storage for the provided snapshot, please increase and retry snapshot" );
shutdown();
Expand All @@ -622,7 +627,7 @@ struct controller_impl {
("genesis_chain_id", genesis_chain_id)("controller_chain_id", chain_id)
);

this->shutdown = shutdown;
this->shutdown = std::move(shutdown);
if( fork_db.head() ) {
if( read_mode == db_read_mode::IRREVERSIBLE && fork_db.head()->id != fork_db.root()->id ) {
fork_db.rollback_head_to_root();
Expand All @@ -644,14 +649,14 @@ struct controller_impl {
} else {
blog.reset( genesis, head->block );
}
init(check_shutdown);
init(std::move(check_shutdown));
}

void startup(std::function<void()> shutdown, std::function<bool()> check_shutdown) {
EOS_ASSERT( db.revision() >= 1, database_exception, "This version of controller::startup does not work with a fresh state database." );
EOS_ASSERT( fork_db.head(), fork_database_exception, "No existing fork database despite existing chain state. Replay required." );

this->shutdown = shutdown;
this->shutdown = std::move(shutdown);
uint32_t lib_num = fork_db.root()->block_num;
auto first_block_num = blog.first_block_num();
if( auto blog_head = blog.head() ) {
Expand All @@ -674,7 +679,7 @@ struct controller_impl {
}
head = fork_db.head();

init(check_shutdown);
init(std::move(check_shutdown));
}


Expand Down Expand Up @@ -3475,9 +3480,16 @@ void controller::validate_tapos( const transaction& trx )const { try {
} FC_CAPTURE_AND_RETHROW() }

void controller::validate_db_available_size() const {
const auto free = db().get_segment_manager()->get_free_memory();
const auto free = db().get_free_memory();
const auto guard = my->conf.state_guard_size;
EOS_ASSERT(free >= guard, database_guard_exception, "database free: ${f}, guard size: ${g}", ("f", free)("g",guard));

// give a change to chainbase to write some pages to disk if memory becomes scarce.
if (is_write_window()) {
if (auto flushed_pages = mutable_db().check_memory_and_flush_if_needed()) {
ilog("CHAINBASE: flushed ${p} pages to disk to decrease memory pressure", ("p", flushed_pages));
}
}
}

bool controller::is_protocol_feature_activated( const digest_type& feature_digest )const {
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ namespace eosio { namespace chain {
bool disable_replay_opts = false;
bool contracts_console = false;
bool allow_ram_billing_in_notify = false;
bool revert_to_private_mode = false;
uint32_t maximum_variable_signature_length = chain::config::default_max_variable_signature_length;
bool disable_all_subjective_mitigations = false; //< for developer & testing purposes, can be configured using `disable-all-subjective-mitigations` when `EOSIO_DEVELOPER` build option is provided
uint32_t terminate_at_block = 0;
Expand Down
10 changes: 9 additions & 1 deletion plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,9 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip
"Subjectively limit the maximum length of variable components in a variable legnth signature to this size in bytes")
("trusted-producer", bpo::value<vector<string>>()->composing(), "Indicate a producer whose blocks headers signed by it will be fully validated, but transactions in those validated blocks will be trusted.")
("database-map-mode", bpo::value<chainbase::pinnable_mapped_file::map_mode>()->default_value(chainbase::pinnable_mapped_file::map_mode::mapped),
"Database map mode (\"mapped\", \"heap\", or \"locked\").\n"
"Database map mode (\"mapped\", \"mapped_private\", \"heap\", or \"locked\").\n"
"In \"mapped\" mode database is memory mapped as a file.\n"
"In \"mapped_private\" mode database is memory mapped as a file using a private mapping (no disk writeback until program exit).\n"
#ifndef _WIN32
"In \"heap\" mode database is preloaded in to swappable memory and will use huge pages if available.\n"
"In \"locked\" mode database is preloaded, locked in to memory, and will use huge pages if available.\n"
Expand Down Expand Up @@ -934,6 +935,13 @@ void chain_plugin_impl::plugin_initialize(const variables_map& options) {

chain_config->db_map_mode = options.at("database-map-mode").as<pinnable_mapped_file::map_mode>();

// when loading a snapshot, all the state will be modified, so temporarily use the `mapped` mode instead
// of `mapped_private` to lower memory requirements.
if (snapshot_path && chain_config->db_map_mode == pinnable_mapped_file::mapped_private) {
chain_config->db_map_mode = pinnable_mapped_file::mapped;
chain_config->revert_to_private_mode = true; // revert to `mapped_private` mode after loading snapshot.
}

#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED
if( options.count("eos-vm-oc-cache-size-mb") )
chain_config->eosvmoc_config.cache_size = options.at( "eos-vm-oc-cache-size-mb" ).as<uint64_t>() * 1024u * 1024u;
Expand Down
2 changes: 1 addition & 1 deletion programs/leap-util/actions/snapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ int snapshot_actions::run_subcommand() {
snap_out.flush();
snap_out.close();
} catch(const database_guard_exception& e) {
std::cerr << "Database is not configured to have enough storage to handle provided snapshot, please increase storage and try aagain" << std::endl;
std::cerr << "Database is not configured to have enough storage to handle provided snapshot, please increase storage and try again" << std::endl;
control.reset();
throw;
}
Expand Down

0 comments on commit 2a0e9c9

Please sign in to comment.