Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize block processing - Part 1 #619

Merged
merged 60 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
439a7a8
GH-529 Do not post unlinkable blocks to the main thread
heifner Aug 13, 2024
9755480
Do not reset sync_source in rejected_block, it is done correctly by c…
heifner Aug 13, 2024
9c48f26
GH-529 Modify add() to return true if added is the new best head
heifner Aug 13, 2024
60b9f18
GH-529 Remove unneeded create_block_handle_future(). Use fork databas…
heifner Aug 13, 2024
17bdffc
GH-529 Make sure sync_recv_block is called for every block. Remove un…
heifner Aug 13, 2024
4f3f8f2
Merge remote-tracking branch 'spring/release/1.0' into GH-529-optimiz…
heifner Aug 15, 2024
126db23
GH-529 Forgot the std:: no move
heifner Aug 15, 2024
4e8070b
Merge remote-tracking branch 'spring/release/1.0' into GH-529-optimiz…
heifner Aug 19, 2024
6bc2899
GH-529 Allow terminate-at-block to be triggered
heifner Aug 19, 2024
6f5408d
GH-529 Do not check terminate-at-block in create_block_handle
heifner Aug 20, 2024
2087abe
Merge branch 'release/1.0' into GH-529-optimize-block-processing
heifner Aug 20, 2024
774f1f8
Merge remote-tracking branch 'spring/release/1.0' into GH-529-optimiz…
heifner Aug 22, 2024
c56535c
Merge branch 'update-disaster-recovery-test-2' into GH-529-optimize-b…
heifner Aug 22, 2024
0e84aa2
Merge branch 'spring' into GH-529-optimize-block-processing
heifner Aug 22, 2024
498aae7
Merge branch 'main' into GH-529-optimize-block-processing
heifner Aug 22, 2024
2308d4b
Merge branch 'GH-621-liveness' into GH-529-optimize-block-processing
heifner Aug 23, 2024
a08a127
Merge branch 'main' into GH-529-optimize-block-processing
heifner Aug 28, 2024
6a60af2
Merge branch 'GH-529-optimize-block-processing' of https://github.com…
heifner Aug 29, 2024
ede5de7
Merge branch 'spring' into GH-529-optimize-block-processing
heifner Aug 29, 2024
57b06d0
Merge branch 'main' into GH-529-optimize-block-processing
heifner Aug 29, 2024
6f34232
GH-529 Update tests to look for new unlinkable_block log message
heifner Aug 29, 2024
7c9e455
GH-529 Remove unneeded handling of unlinkable blocks
heifner Aug 29, 2024
7fbeede
GH-670 Backport fix from GH-671 for testing of syncing
heifner Aug 29, 2024
c62d84a
GH-670 Add a simple work around reporting of unlinkable blocks around…
heifner Aug 29, 2024
ad3e3c4
GH-529 WIP: Change maybe_switch_forks to always use forkdb and ignore…
heifner Aug 30, 2024
1b7a8c3
GH-529 Rename maybe_switch_forks to apply_blocks. Rename controller::…
heifner Aug 30, 2024
af3065b
GH-529 Handle case where there is no pending best head, forkdb at root
heifner Aug 30, 2024
fb830e8
GH-529 block_state_ptr already added to forkdb
heifner Aug 31, 2024
18163e3
Merge remote-tracking branch 'spring/test-signals' into GH-529-optimi…
heifner Sep 2, 2024
41c887b
GH-529 Remove unneeded accept_block
heifner Sep 2, 2024
3d216b1
GH-529 emit accepted_block_header during replay
heifner Sep 2, 2024
3b1f0f5
GH-529 Rename push_block to apply_blocks to describe what it now does…
heifner Sep 2, 2024
b2b6023
Merge remote-tracking branch 'spring/main' into GH-529-optimize-block…
heifner Sep 2, 2024
090fb77
GH-529 Rename create_block_handle to accept_block
heifner Sep 2, 2024
d461c2b
GH-529 Rename replay_push_irreversible_block to replay_irreversible_b…
heifner Sep 2, 2024
ca75538
GH-529 Move block_report to controller.cpp has no longer used outside…
heifner Sep 2, 2024
57cafa6
Merge remote-tracking branch 'spring/test-signals' into GH-529-optimi…
heifner Sep 3, 2024
2c26474
Merge remote-tracking branch 'spring/main' into GH-529-optimize-block…
heifner Sep 12, 2024
d474c20
GH-529 Move prometheus produced block and incoming block metrics crea…
heifner Sep 12, 2024
80ae3ae
GH-529 Fix merge issue
heifner Sep 12, 2024
2f3c110
Merge remote-tracking branch 'spring/main' into GH-529-optimize-block…
heifner Sep 12, 2024
a39df93
Merge remote-tracking branch 'spring/main' into GH-529-optimize-block…
heifner Sep 12, 2024
a323c16
Merge branch 'main' into GH-529-optimize-block-processing
heifner Sep 15, 2024
d9330b7
GH-529 Add back log_irreversible
heifner Sep 17, 2024
768059c
GH-529 Use a struct instead of a tuple
heifner Sep 18, 2024
c7fb0e6
GH-529 Change an EOS_ASSERT to an assert and add a comment
heifner Sep 18, 2024
569a02d
Merge remote-tracking branch 'spring/main' into GH-529-optimize-block…
heifner Sep 19, 2024
0d326d5
GH-529 Remove dead code. Since blocks are put into the forkdb immedia…
heifner Sep 19, 2024
5d4f108
GH-529 Add some tests for forkdb.add() returning new best head
heifner Sep 19, 2024
ad1faf5
GH-773 Use named variables for branches pair
heifner Sep 19, 2024
a2638c3
GH-529 optimize is_new_best_head determination
heifner Sep 19, 2024
b1cef5b
GH-529 Rename is_best_head to is_new_best_head and other cleanup
heifner Sep 19, 2024
61547cc
GH-529 Remove old comment
heifner Sep 20, 2024
e4a7b3d
GH-529 Use comparison of passed in block instead of checking index it…
heifner Sep 20, 2024
abe9283
Merge branch 'main' into GH-529-optimize-block-processing
heifner Sep 25, 2024
8175b7c
GH-529 Tweak throttle test so it throttles over a longer time frame t…
heifner Sep 25, 2024
e8e120b
GH-529 Don't post sending of blocks or votes to dispatcher thread. No…
heifner Sep 25, 2024
8430c00
GH-529 Switch p2p_sync_throttle test to long_running_tests since time…
heifner Sep 25, 2024
087e77f
GH-529 ThrottledNode can sync very slowly
heifner Sep 25, 2024
ef976a0
GH-529 Forkdb no longer accessed so we can log in log_applied which i…
heifner Sep 25, 2024
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
608 changes: 239 additions & 369 deletions libraries/chain/controller.cpp

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions libraries/chain/fork_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ namespace eosio::chain {

void open_impl( const char* desc, const std::filesystem::path& fork_db_file, fc::cfile_datastream& ds, validator_t& validator );
void close_impl( std::ofstream& out );
void add_impl( const bsp_t& n, ignore_duplicate_t ignore_duplicate, bool validate, validator_t& validator );
bool add_impl( const bsp_t& n, ignore_duplicate_t ignore_duplicate, bool validate, validator_t& validator );
bool is_valid() const;

bsp_t get_block_impl( const block_id_type& id, include_root_t include_root = include_root_t::no ) const;
Expand Down Expand Up @@ -240,7 +240,7 @@ namespace eosio::chain {
}

template <class BSP>
void fork_database_impl<BSP>::add_impl(const bsp_t& n, ignore_duplicate_t ignore_duplicate,
bool fork_database_impl<BSP>::add_impl(const bsp_t& n, ignore_duplicate_t ignore_duplicate,
bool validate, validator_t& validator) {
EOS_ASSERT( root, fork_database_exception, "root not yet set" );
EOS_ASSERT( n, fork_database_exception, "attempt to add null block state" );
Expand Down Expand Up @@ -280,17 +280,17 @@ namespace eosio::chain {
auto inserted = index.insert(n);
EOS_ASSERT(ignore_duplicate == ignore_duplicate_t::yes || inserted.second, fork_database_exception,
"duplicate block added: ${id}", ("id", n->id()));

return inserted.second && n == head_impl(include_root_t::no);
}

template<class BSP>
void fork_database_t<BSP>::add( const bsp_t& n, ignore_duplicate_t ignore_duplicate ) {
bool fork_database_t<BSP>::add( const bsp_t& n, ignore_duplicate_t ignore_duplicate ) {
std::lock_guard g( my->mtx );
my->add_impl( n, ignore_duplicate, false,
[]( block_timestamp_type timestamp,
const flat_set<digest_type>& cur_features,
const vector<digest_type>& new_features )
{}
);
return my->add_impl(n, ignore_duplicate, false,
[](block_timestamp_type timestamp,
const flat_set<digest_type>& cur_features,
const vector<digest_type>& new_features) {});
}

template<class BSP>
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/eosio/chain/block_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace eosio::chain {

// Created via controller::create_block_handle(const block_id_type& id, const signed_block_ptr& b)
// Created via controller::accept_block(const block_id_type& id, const signed_block_ptr& b)
// Valid to request id and signed_block_ptr it was created from.
struct block_handle {
private:
Expand Down
81 changes: 53 additions & 28 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,46 @@ namespace eosio::vm { class wasm_allocator; }

namespace eosio::chain {

struct speculative_block_metrics {
account_name block_producer{};
uint32_t block_num = 0;
int64_t block_total_time_us = 0;
int64_t block_idle_us = 0;
std::size_t num_success_trx = 0;
int64_t success_trx_time_us = 0;
std::size_t num_fail_trx = 0;
int64_t fail_trx_time_us = 0;
std::size_t num_transient_trx = 0;
int64_t transient_trx_time_us = 0;
int64_t block_other_time_us = 0;
};

struct produced_block_metrics : public speculative_block_metrics {
std::size_t unapplied_transactions_total = 0;
std::size_t subjective_bill_account_size_total = 0;
std::size_t scheduled_trxs_total = 0;
std::size_t trxs_produced_total = 0;
uint64_t cpu_usage_us = 0;
int64_t total_elapsed_time_us = 0;
int64_t total_time_us = 0;
uint64_t net_usage_us = 0;

uint32_t last_irreversible = 0;
uint32_t head_block_num = 0;
};

struct incoming_block_metrics {
std::size_t trxs_incoming_total = 0;
uint64_t cpu_usage_us = 0;
int64_t total_elapsed_time_us = 0;
int64_t total_time_us = 0;
uint64_t net_usage_us = 0;
int64_t block_latency_us = 0;

uint32_t last_irreversible = 0;
uint32_t head_block_num = 0;
};

using bls_pub_priv_key_map_t = std::map<std::string, std::string>;
struct finalizer_policy;

Expand Down Expand Up @@ -182,41 +222,23 @@ namespace eosio::chain {
fc::time_point block_deadline, fc::microseconds max_transaction_time,
uint32_t billed_cpu_time_us, bool explicit_billed_cpu_time );

struct block_report {
size_t total_net_usage = 0;
size_t total_cpu_usage_us = 0;
fc::microseconds total_elapsed_time{};
fc::microseconds total_time{};
};

void assemble_and_complete_block( block_report& br, const signer_callback_type& signer_callback );
void assemble_and_complete_block( const signer_callback_type& signer_callback );
void sign_block( const signer_callback_type& signer_callback );
void commit_block(block_report& br);
void commit_block();
void testing_allow_voting(bool val);
bool get_testing_allow_voting_flag();
void set_async_voting(async_t val);
void set_async_aggregation(async_t val);
void maybe_switch_forks(const forked_callback_t& cb, const trx_meta_cache_lookup& trx_lookup);

// thread-safe
std::future<block_handle> create_block_handle_future( const block_id_type& id, const signed_block_ptr& b );
// thread-safe
// returns empty optional if block b is not immediately ready to be processed
std::optional<block_handle> create_block_handle( const block_id_type& id, const signed_block_ptr& b ) const;

/**
* @param br returns statistics for block
* @param b block to push, created by create_block_handle
* @param cb calls cb with forked applied transactions for each forked block
* @param trx_lookup user provided lookup function for externally cached transaction_metadata
*/
void push_block( block_report& br,
const block_handle& b,
const forked_callback_t& cb,
const trx_meta_cache_lookup& trx_lookup );
/// Apply any blocks that are ready from the forkdb
void apply_blocks(const forked_callback_t& cb, const trx_meta_cache_lookup& trx_lookup);

/// Accept block into fork_database
void accept_block(const block_handle& b);
struct accepted_block_handle {
const bool is_new_best_head = false; // true if new best head
std::optional<block_handle> block; // empty optional if block is unlinkable
};
// thread-safe
accepted_block_handle accept_block( const block_id_type& id, const signed_block_ptr& b ) const;

boost::asio::io_context& get_thread_pool();

Expand Down Expand Up @@ -461,6 +483,9 @@ namespace eosio::chain {
// is the bls key a registered finalizer key of this node, thread safe
bool is_node_finalizer_key(const bls_public_key& key) const;

void register_update_produced_block_metrics(std::function<void(produced_block_metrics)>&&);
void register_update_speculative_block_metrics(std::function<void(speculative_block_metrics)>&&);
void register_update_incoming_block_metrics(std::function<void(incoming_block_metrics)>&&);
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved

private:
const my_finalizers_t& get_node_finalizers() const; // used for tests (purpose is inspecting fsi).
Expand Down
3 changes: 2 additions & 1 deletion libraries/chain/include/eosio/chain/fork_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ namespace eosio::chain {
/**
* Add block state to fork database.
* Must link to existing block in fork database or the root.
* @return true if n becomes the new best head (and was not the best head before)
*/
void add( const bsp_t& next_block, ignore_duplicate_t ignore_duplicate );
bool add( const bsp_t& n, ignore_duplicate_t ignore_duplicate );

void remove( const block_id_type& id );

Expand Down
9 changes: 4 additions & 5 deletions libraries/testing/include/eosio/testing/tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -811,11 +811,10 @@ namespace eosio::testing {
}

void validate_push_block(const signed_block_ptr& sb) {
auto btf = validating_node->create_block_handle_future( sb->calculate_id(), sb );
controller::block_report br;
block_handle bh = btf.get();
validating_node->push_block( br, bh, {}, trx_meta_cache_lookup{} );
_check_for_vote_if_needed(*validating_node, bh);
auto [best_head, obh] = validating_node->accept_block( sb->calculate_id(), sb );
EOS_ASSERT(obh, unlinkable_block_exception, "block did not link ${b}", ("b", sb->calculate_id()));
validating_node->apply_blocks( {}, trx_meta_cache_lookup{} );
_check_for_vote_if_needed(*validating_node, *obh);
}

signed_block_ptr produce_empty_block( fc::microseconds skip_time = default_skip_time )override {
Expand Down
20 changes: 10 additions & 10 deletions libraries/testing/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,11 @@ namespace eosio::testing {

void base_tester::push_block(const signed_block_ptr& b) {
auto block_id = b->calculate_id();
auto bhf = control->create_block_handle_future(block_id, b);
auto [best_fork, obh] = control->accept_block(block_id, b);
unapplied_transactions.add_aborted( control->abort_block() );
controller::block_report br;
block_handle bh = bhf.get();
control->push_block( br, bh, [this]( const transaction_metadata_ptr& trx ) {
EOS_ASSERT(obh, unlinkable_block_exception, "block did not link ${b}", ("b", b->calculate_id()));
const block_handle& bh = *obh;
control->apply_blocks( [this]( const transaction_metadata_ptr& trx ) {
unapplied_transactions.add_forked( trx );
}, [this]( const transaction_id_type& id ) {
return unapplied_transactions.get_trx( id );
Expand Down Expand Up @@ -564,8 +564,7 @@ namespace eosio::testing {
}
});

controller::block_report br;
control->assemble_and_complete_block( br, [&]( digest_type d ) {
control->assemble_and_complete_block( [&]( digest_type d ) {
std::vector<signature_type> result;
result.reserve(signing_keys.size());
for (const auto& k: signing_keys)
Expand All @@ -574,7 +573,7 @@ namespace eosio::testing {
return result;
} );

control->commit_block(br);
control->commit_block();

block_handle head = control->head();

Expand Down Expand Up @@ -1214,10 +1213,11 @@ namespace eosio::testing {

auto block = a.control->fetch_block_by_number(i);
if( block ) { //&& !b.control->is_known_block(block->id()) ) {
auto btf = b.control->create_block_handle_future( block->calculate_id(), block );
auto id = block->calculate_id();
auto [best_head, obh] = b.control->accept_block( id, block );
b.control->abort_block();
controller::block_report br;
b.control->push_block(br, btf.get(), {}, trx_meta_cache_lookup{}); //, eosio::chain::validation_steps::created_block);
EOS_ASSERT(obh, unlinkable_block_exception, "block did not link ${b}", ("b", id));
b.control->apply_blocks({}, trx_meta_cache_lookup{});
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace eosio::chain::plugin_interface {
namespace incoming {
namespace methods {
// synchronously push a block/trx to a single provider, block_state_legacy_ptr may be null
using block_sync = method_decl<chain_plugin_interface, bool(const signed_block_ptr&, const block_id_type&, const std::optional<block_handle>&), first_provider_policy>;
using block_sync = method_decl<chain_plugin_interface, bool(const signed_block_ptr&, const block_id_type&, const block_handle&), first_provider_policy>;
using transaction_async = method_decl<chain_plugin_interface, void(const packed_transaction_ptr&, bool, transaction_metadata::trx_type, bool, next_function<transaction_trace_ptr>), first_provider_policy>;
}
}
Expand Down
9 changes: 6 additions & 3 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,8 +1208,8 @@ chain_apis::read_only chain_plugin::get_read_only_api(const fc::microseconds& ht
}


bool chain_plugin::accept_block(const signed_block_ptr& block, const block_id_type& id, const std::optional<block_handle>& obt ) {
return my->incoming_block_sync_method(block, id, obt);
bool chain_plugin::accept_block(const signed_block_ptr& block, const block_id_type& id, const block_handle& bh ) {
return my->incoming_block_sync_method(block, id, bh);
}

void chain_plugin::accept_transaction(const chain::packed_transaction_ptr& trx, next_function<chain::transaction_trace_ptr> next) {
Expand Down Expand Up @@ -2116,7 +2116,10 @@ fc::variant read_only::get_block_header_state(const get_block_header_state_param
void read_write::push_block(read_write::push_block_params&& params, next_function<read_write::push_block_results> next) {
try {
auto b = std::make_shared<signed_block>( std::move(params) );
app().get_method<incoming::methods::block_sync>()(b, b->calculate_id(), std::optional<block_handle>{});
block_id_type id = b->calculate_id();
auto [best_head, obh] = db.accept_block( id, b );
EOS_ASSERT(obh, unlinkable_block_exception, "block did not link ${b}", ("b", id));
app().get_method<incoming::methods::block_sync>()(b, id, *obh);
} catch ( boost::interprocess::bad_alloc& ) {
handle_db_exhaustion();
} catch ( const std::bad_alloc& ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ class chain_plugin : public plugin<chain_plugin> {
chain_apis::read_write get_read_write_api(const fc::microseconds& http_max_response_time);
chain_apis::read_only get_read_only_api(const fc::microseconds& http_max_response_time) const;

bool accept_block( const chain::signed_block_ptr& block, const chain::block_id_type& id, const std::optional<chain::block_handle>& obt );
bool accept_block( const chain::signed_block_ptr& block, const chain::block_id_type& id, const chain::block_handle& bh );
void accept_transaction(const chain::packed_transaction_ptr& trx, chain::plugin_interface::next_function<chain::transaction_trace_ptr> next);

// Only call this after plugin_initialize()!
Expand Down
Loading