This repository was archived by the owner on Nov 6, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Benchmarks for block verification #11035
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
09a5612
WIP
dvdplm 926ce64
wip
dvdplm 33ff04b
Benchmarks for block verification
dvdplm 6d9666f
Cleanup, fix CI
dvdplm 3f39282
Bash syntax error
dvdplm 72fe372
One more try
dvdplm 5ffa37f
Fix review grumbles
dvdplm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| // Copyright 2015-2019 Parity Technologies (UK) Ltd. | ||
| // This file is part of Parity Ethereum. | ||
|
|
||
| // Parity Ethereum is free software: you can redistribute it and/or modify | ||
| // it under the terms of the GNU General Public License as published by | ||
| // the Free Software Foundation, either version 3 of the License, or | ||
| // (at your option) any later version. | ||
|
|
||
| // Parity Ethereum is distributed in the hope that it will be useful, | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| // GNU General Public License for more details. | ||
|
|
||
| // You should have received a copy of the GNU General Public License | ||
| // along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>. | ||
|
|
||
| //! benchmarking for verification | ||
|
|
||
| use std::collections::BTreeMap; | ||
|
|
||
| use common_types::verification::Unverified; | ||
| use criterion::{Criterion, criterion_group, criterion_main}; | ||
| use ethash::{EthashParams, Ethash}; | ||
| use ethereum_types::U256; | ||
| use ethcore::client::TestBlockChainClient; | ||
| use spec::new_constantinople_test_machine; | ||
| use tempdir::TempDir; | ||
|
|
||
| use ::verification::{ | ||
|
niklasad1 marked this conversation as resolved.
|
||
| FullFamilyParams, | ||
| verification, | ||
| test_helpers::TestBlockChain, | ||
| }; | ||
|
|
||
| // These are current production values. Needed when using real blocks. | ||
| fn ethash_params() -> EthashParams { | ||
| EthashParams { | ||
| minimum_difficulty: U256::from(131072), | ||
| difficulty_bound_divisor: U256::from(2048), | ||
| difficulty_increment_divisor: 10, | ||
| metropolis_difficulty_increment_divisor: 9, | ||
| duration_limit: 13, | ||
| homestead_transition: 1150000, | ||
| difficulty_hardfork_transition: u64::max_value(), | ||
| difficulty_hardfork_bound_divisor: U256::from(2048), | ||
| bomb_defuse_transition: u64::max_value(), | ||
| eip100b_transition: 4370000, | ||
| ecip1010_pause_transition: u64::max_value(), | ||
| ecip1010_continue_transition: u64::max_value(), | ||
| ecip1017_era_rounds: u64::max_value(), | ||
| block_reward: { | ||
| let mut m = BTreeMap::<u64, U256>::new(); | ||
| m.insert(0, 5000000000000000000u64.into()); | ||
| m.insert(4370000, 3000000000000000000u64.into()); | ||
| m.insert(7280000, 2000000000000000000u64.into()); | ||
| m | ||
| }, | ||
| expip2_transition: u64::max_value(), | ||
| expip2_duration_limit: 30, | ||
| block_reward_contract_transition: 0, | ||
| block_reward_contract: None, | ||
| difficulty_bomb_delays: { | ||
| let mut m = BTreeMap::new(); | ||
|
niklasad1 marked this conversation as resolved.
|
||
| m.insert(4370000, 3000000); | ||
| m.insert(7280000, 2000000); | ||
| m | ||
| }, | ||
| progpow_transition: u64::max_value() | ||
| } | ||
| } | ||
|
|
||
| fn build_ethash() -> Ethash { | ||
| let machine = new_constantinople_test_machine(); | ||
| let ethash_params = ethash_params(); | ||
| let cache_dir = TempDir::new("").unwrap(); | ||
| Ethash::new( | ||
| cache_dir.path(), | ||
| ethash_params, | ||
| machine, | ||
| None | ||
| ) | ||
| } | ||
|
|
||
| fn block_verification(c: &mut Criterion) { | ||
| const PROOF: &str = "bytes from disk are ok"; | ||
|
|
||
| let ethash = build_ethash(); | ||
|
|
||
| // A fairly large block (32kb) with one uncle | ||
| let rlp_8481476 = include_bytes!("./8481476-one-uncle.rlp").to_vec(); | ||
| // Parent of #8481476 | ||
| let rlp_8481475 = include_bytes!("./8481475.rlp").to_vec(); | ||
| // Parent of the uncle in #8481476 | ||
| let rlp_8481474 = include_bytes!("./8481474-parent-to-uncle.rlp").to_vec(); | ||
|
|
||
| // Phase 1 verification | ||
| c.bench_function("verify_block_basic", |b| { | ||
| let block = Unverified::from_rlp(rlp_8481476.clone()).expect(PROOF); | ||
| b.iter(|| { | ||
| assert!(verification::verify_block_basic( | ||
| &block, | ||
| ðash, | ||
| true | ||
| ).is_ok()); | ||
| }) | ||
| }); | ||
|
|
||
| // Phase 2 verification | ||
| c.bench_function("verify_block_unordered", |b| { | ||
| let block = Unverified::from_rlp(rlp_8481476.clone()).expect(PROOF); | ||
| b.iter( || { | ||
| assert!(verification::verify_block_unordered( | ||
| block.clone(), | ||
| ðash, | ||
| true | ||
| ).is_ok()); | ||
| }) | ||
| }); | ||
|
|
||
| // Phase 3 verification | ||
| let block = Unverified::from_rlp(rlp_8481476.clone()).expect(PROOF); | ||
| let preverified = verification::verify_block_unordered(block, ðash, true).expect(PROOF); | ||
| let parent = Unverified::from_rlp(rlp_8481475.clone()).expect(PROOF); | ||
|
|
||
| // "partial" means we skip uncle and tx verification | ||
| c.bench_function("verify_block_family (partial)", |b| { | ||
| b.iter(|| { | ||
| if let Err(e) = verification::verify_block_family::<TestBlockChainClient>( | ||
| &preverified.header, | ||
| &parent.header, | ||
| ðash, | ||
| None | ||
| ) { | ||
| panic!("verify_block_family (partial) ERROR: {:?}", e); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| let mut block_provider = TestBlockChain::new(); | ||
| block_provider.insert(rlp_8481476.clone()); // block to verify | ||
| block_provider.insert(rlp_8481475.clone()); // parent | ||
| block_provider.insert(rlp_8481474.clone()); // uncle's parent | ||
|
|
||
| let client = TestBlockChainClient::default(); | ||
| c.bench_function("verify_block_family (full)", |b| { | ||
| b.iter(|| { | ||
| let full = FullFamilyParams { block: &preverified, block_provider: &block_provider, client: &client }; | ||
| if let Err(e) = verification::verify_block_family::<TestBlockChainClient>( | ||
| &preverified.header, | ||
| &parent.header, | ||
| ðash, | ||
| Some(full), | ||
| ) { | ||
| panic!("verify_block_family (full) ERROR: {:?}", e) | ||
| } | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| criterion_group!(benches, block_verification); | ||
| criterion_main!(benches); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| // Copyright 2015-2019 Parity Technologies (UK) Ltd. | ||
| // This file is part of Parity Ethereum. | ||
|
|
||
| // Parity Ethereum is free software: you can redistribute it and/or modify | ||
| // it under the terms of the GNU General Public License as published by | ||
| // the Free Software Foundation, either version 3 of the License, or | ||
| // (at your option) any later version. | ||
|
|
||
| // Parity Ethereum is distributed in the hope that it will be useful, | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| // GNU General Public License for more details. | ||
|
|
||
| // You should have received a copy of the GNU General Public License | ||
| // along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>. | ||
|
|
||
| //! Verification test helpers. | ||
|
|
||
| use std::collections::HashMap; | ||
|
|
||
| use blockchain::{BlockProvider, BlockChain, BlockDetails, TransactionAddress, BlockReceipts}; | ||
| use common_types::{ | ||
| BlockNumber, | ||
| encoded, | ||
| verification::Unverified, | ||
| log_entry::{LogEntry, LocalizedLogEntry}, | ||
| }; | ||
| use ethereum_types::{BloomRef, H256}; | ||
| use parity_bytes::Bytes; | ||
|
|
||
| #[derive(Default)] | ||
| pub struct TestBlockChain { | ||
|
niklasad1 marked this conversation as resolved.
|
||
| blocks: HashMap<H256, Bytes>, | ||
| numbers: HashMap<BlockNumber, H256>, | ||
| } | ||
|
|
||
| impl TestBlockChain { | ||
| pub fn new() -> Self { TestBlockChain::default() } | ||
|
|
||
| pub fn insert(&mut self, bytes: Bytes) { | ||
| let header = Unverified::from_rlp(bytes.clone()).unwrap().header; | ||
| let hash = header.hash(); | ||
| self.blocks.insert(hash, bytes); | ||
| self.numbers.insert(header.number(), hash); | ||
| } | ||
| } | ||
|
|
||
| impl BlockProvider for TestBlockChain { | ||
| fn is_known(&self, hash: &H256) -> bool { | ||
| self.blocks.contains_key(hash) | ||
| } | ||
|
|
||
| fn first_block(&self) -> Option<H256> { | ||
| unimplemented!() | ||
| } | ||
|
|
||
| fn best_ancient_block(&self) -> Option<H256> { | ||
| None | ||
| } | ||
|
|
||
| /// Get raw block data | ||
| fn block(&self, hash: &H256) -> Option<encoded::Block> { | ||
| self.blocks.get(hash).cloned().map(encoded::Block::new) | ||
| } | ||
|
|
||
| /// Get the familial details concerning a block. | ||
| fn block_details(&self, hash: &H256) -> Option<BlockDetails> { | ||
| self.blocks.get(hash).map(|bytes| { | ||
| let header = Unverified::from_rlp(bytes.to_vec()).unwrap().header; | ||
| BlockDetails { | ||
| number: header.number(), | ||
| total_difficulty: *header.difficulty(), | ||
| parent: *header.parent_hash(), | ||
| children: Vec::new(), | ||
| is_finalized: false, | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| /// Get the hash of given block's number. | ||
| fn block_hash(&self, index: BlockNumber) -> Option<H256> { | ||
| self.numbers.get(&index).cloned() | ||
| } | ||
|
|
||
| fn transaction_address(&self, _hash: &H256) -> Option<TransactionAddress> { | ||
| unimplemented!() | ||
| } | ||
|
|
||
| fn block_receipts(&self, _hash: &H256) -> Option<BlockReceipts> { | ||
| unimplemented!() | ||
| } | ||
|
|
||
| fn block_header_data(&self, hash: &H256) -> Option<encoded::Header> { | ||
| self.block(hash) | ||
| .map(|b| b.header_view().rlp().as_raw().to_vec()) | ||
| .map(encoded::Header::new) | ||
| } | ||
|
|
||
| fn block_body(&self, hash: &H256) -> Option<encoded::Body> { | ||
| self.block(hash) | ||
| .map(|b| BlockChain::block_to_body(&b.into_inner())) | ||
| .map(encoded::Body::new) | ||
| } | ||
|
|
||
| fn blocks_with_bloom<'a, B, I, II>(&self, _blooms: II, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec<BlockNumber> | ||
| where BloomRef<'a>: From<B>, II: IntoIterator<Item = B, IntoIter = I> + Copy, I: Iterator<Item = B>, Self: Sized { | ||
| unimplemented!() | ||
| } | ||
|
|
||
| fn logs<F>(&self, _blocks: Vec<H256>, _matches: F, _limit: Option<usize>) -> Vec<LocalizedLogEntry> | ||
| where F: Fn(&LogEntry) -> bool, Self: Sized { | ||
| unimplemented!() | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Cloneis used for benchmarks/tests?Why not
#[cfg_attr(any(foo, bar), derive(Clone)]?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.
Yes, that is the reason. It's more convenience than necessity though. In general though, why is it bad to derive
Clone? Reading https://rust-lang-nursery.github.io/api-guidelines/interoperability.html#c-common-traits it seems idiomatic to do so whenever it's convenient?Uh oh!
There was an error while loading. Please reload this page.
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.
nothing bad I guess but it might have the reasoning that such big structures should not be cloned which are enforced by
rustcwhen noClone impl existsbut I don't know really just guessing!EDIT: It would produce a slightly bigger binary I guess but so small that it is probably negligible