-
Notifications
You must be signed in to change notification settings - Fork 648
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
Parallel preprocessing of blocks + transactions #1360
Conversation
good stuff peter! |
Thanks, but not yet. :-/ |
ah!..got overexcited over the "working version" commit :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it's still WIP, perhaps will have answer later.
e2d32cb
to
a3a5612
Compare
libraries/app/application.cpp
Outdated
graphene::chain::database::skip_tapos_check | | ||
graphene::chain::database::skip_witness_schedule_check; | ||
if( _options->count("revalidate-blockchain") ) // see also handle_block() | ||
skip = _options->count("force-validate") ? 0 : graphene::chain::database::skip_transaction_signatures; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I think it's better to replace
0
withgraphene::chain::database::skip_nothing
. - Code readability here looks a bit poor. Now it reads:
declare skip = something;
if (condition A)
{
skip = condition B ? something else : yet something else;
}
How about change the if
to ?:
declare skip = condition A ? condition B ? something else : yet something else : something;
or change the ?:
to if else
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And need to resolve FC conflicts.
libraries/app/application.cpp
Outdated
@@ -961,9 +979,10 @@ void application::set_program_options(boost::program_options::options_descriptio | |||
"Path to create a Genesis State at. If a well-formed JSON file exists at the path, it will be parsed and any " | |||
"missing fields in a Genesis State will be added, and any unknown fields will be removed. If no file or an " | |||
"invalid file is found, it will be replaced with an example Genesis State.") | |||
("replay-blockchain", "Rebuild object graph by replaying all blocks") | |||
("replay-blockchain", "Rebuild object graph by replaying all blocks without validatino") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
libraries/chain/db_block.cpp
Outdated
uint32_t chunks = fc::asio::default_io_service_scope::get_num_threads(); | ||
uint32_t chunk_size = block.transactions.size() / chunks; | ||
if( chunks * chunk_size < block.transactions.size() ) | ||
chunk_size++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it essentially rounding up? If it's true then can code like this:
uint32_t chunk_size = ( block.transactions.size() + chunks - 1 ) / chunks;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
void validate() const; | ||
digest_type digest()const; | ||
virtual const transaction_id_type& id()const; | ||
virtual void validate() const; | ||
/// Calculate the digest used for signature validation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment should be moved to correct place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -307,20 +305,17 @@ const flat_set<public_key_type>& signed_transaction::get_signature_keys( const c | |||
{ try { | |||
// Strictly we should check whether the given chain ID is same as the one used to initialize the `signees` field. | |||
// However, we don't pass in another chain ID so far, for better performance, we skip the check. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comments should be removed if signees are calculated every time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved
@@ -307,20 +305,17 @@ const flat_set<public_key_type>& signed_transaction::get_signature_keys( const c | |||
{ try { | |||
// Strictly we should check whether the given chain ID is same as the one used to initialize the `signees` field. | |||
// However, we don't pass in another chain ID so far, for better performance, we skip the check. | |||
if( signees.empty() && !signatures.empty() ) | |||
auto d = sig_digest( chain_id ); | |||
flat_set<public_key_type> result; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a non-default key_compare
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That wouldn't help, because then the set has to be re-sorted when assigning to _signees
field.
Unless we also change the sorting order there, which means the signature of this method has to be changed as well, and all places that use it... it simply doesn't pay out, see #1401 .
precomputable_transaction( const signed_transaction& tx ) : signed_transaction(tx) {}; | ||
precomputable_transaction( signed_transaction&& tx ) : signed_transaction(tx) {}; | ||
|
||
virtual const transaction_id_type& id()const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can add an override
keyword to overridden functions here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
_index[space][type]->save( _data_dir / "object_database.tmp" / fc::to_string(space)/fc::to_string(type) ); | ||
tasks.push_back( fc::do_parallel( [this,space,type] () { | ||
_index[space][type]->save( _data_dir / "object_database.tmp" / fc::to_string(space)/fc::to_string(type) ); | ||
} ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Does this really increase performance? Isn't IO the bottleneck here?
- Perhaps better if we adopt the behavior of ChainBase, store not only data but also indexes, to improve startup speed (may slow down shutdown speed though). This belongs to another ticket.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IO isn't necessarily the bottleneck, e. g. when restarting a node the previously saved data might still be in system buffers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is save
aka writing but not reading. When we're writing, usually the data has changed, even if it didn't change much, since we're writing to temporary (aka different) files, so the buffer doesn't help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course disk buffer helps when writing.
On a system with a slow disk and the bare minimum of RAM you're right, parallelizing won't help - but it won't hurt either.
With sufficient buffer memory, or on a RAM-disk, parallel saving should be faster.
{ | ||
wlog( "Reindexing terminated due to gap: Block ${i} does not exist!", ("i", i) ); | ||
uint32_t dropped_count = 0; | ||
while( true ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still believe this (old) code is inefficient. But it may belong to another ticket with lower priority.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.
@@ -105,6 +105,7 @@ void delayed_node_plugin::sync_with_trusted_node() | |||
fc::optional<graphene::chain::signed_block> block = my->database_api->get_block( db.head_block_num()+1 ); | |||
FC_ASSERT(block, "Trusted node claims it has blocks it doesn't actually have."); | |||
ilog("Pushing block #${n}", ("n", block->block_num())); | |||
db.precompute_parallel( *block, graphene::chain::database::skip_nothing ).wait(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can adopt same approach used in reindex here for even better performance, IMHO low priority though. Add a TODO?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
@@ -170,6 +170,11 @@ extern uint32_t GRAPHENE_TESTING_GENESIS_TIMESTAMP; | |||
|
|||
namespace graphene { namespace chain { | |||
|
|||
class clearable_block : public signed_block { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please write some comments for this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
32e9619
to
81f7520
Compare
Rebased. Will bump fc after bitshares/bitshares-fc#78 has been merged. |
Timings taken up to block 31,000,000 with various core versions (also see #1371), on a quad-core (with hyperthreading) "Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz", 64G RAM, default config:
(Resync was done at different times of day, fluctuations due to network conditions are to be expected.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good. I believe fc is all set. Please fix the conflict and I will approve this after some final testing. Nice work!
…_transaction_signatures
…of signed_transaction
81f7520
to
2c01109
Compare
Rebased on latest develop + bumped fc to latest master |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good. Tested with Ubuntu 18.10 / Boost 1.67 / OpenSSL 1.1.0. chain_test runs with no errors detected. Thank you for tackling this.
Work in progress, do not merge yet!Will
some dayresolve #1079 insofar as it is possible without modifying consensus.This includes the changes from #1359 . Requires bitshares/bitshares-fc#78 .
Status: seems to be working, at least with boost-1.60. Testing.