From 448ce2adff88b5c8d65681fa3708932cd965fa5c Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 28 Oct 2019 18:05:52 +0300 Subject: [PATCH] Basic extrinsic pool benchmarks (#3922) * Working bench for 50 sequental * configured benches * fix warnings * Optimize and fix issues * add preamble * Fix benchmarks. * fix compilation * remove unneeded features for now --- substrate/Cargo.lock | 1 + .../core/transaction-pool/graph/Cargo.toml | 5 + .../transaction-pool/graph/benches/basics.rs | 165 ++++++++++++++++++ .../core/transaction-pool/graph/src/pool.rs | 1 - 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 substrate/core/transaction-pool/graph/benches/basics.rs diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index d369bbb5f6..4bade61225 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -5788,6 +5788,7 @@ name = "substrate-transaction-graph" version = "2.0.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/core/transaction-pool/graph/Cargo.toml b/substrate/core/transaction-pool/graph/Cargo.toml index fa0d6f14b6..4b628079cd 100644 --- a/substrate/core/transaction-pool/graph/Cargo.toml +++ b/substrate/core/transaction-pool/graph/Cargo.toml @@ -18,3 +18,8 @@ assert_matches = "1.3.0" env_logger = "0.7.0" codec = { package = "parity-scale-codec", version = "1.0.0" } test_runtime = { package = "substrate-test-runtime", path = "../../test-runtime" } +criterion = "0.3" + +[[bench]] +name = "basics" +harness = false diff --git a/substrate/core/transaction-pool/graph/benches/basics.rs b/substrate/core/transaction-pool/graph/benches/basics.rs new file mode 100644 index 0000000000..dcd725ce46 --- /dev/null +++ b/substrate/core/transaction-pool/graph/benches/basics.rs @@ -0,0 +1,165 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +use criterion::{criterion_group, criterion_main, Criterion}; + +use futures::executor::block_on; +use substrate_transaction_graph::*; +use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransaction}; +use codec::Encode; +use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; +use sr_primitives::{ + generic::BlockId, + transaction_validity::{TransactionValidity, TransactionTag as Tag}, +}; +use primitives::blake2_256; + +#[derive(Clone, Debug, Default)] +struct TestApi { + nonce_dependant: bool, +} + +impl TestApi { + fn new_dependant() -> Self { + TestApi { nonce_dependant: true } + } +} + +fn to_tag(nonce: u64, from: AccountId) -> Tag { + let mut data = [0u8; 40]; + data[..8].copy_from_slice(&nonce.to_le_bytes()[..]); + data[8..].copy_from_slice(&from.0[..]); + data.to_vec() +} + +impl ChainApi for TestApi { + type Block = Block; + type Hash = H256; + type Error = error::Error; + type ValidationFuture = futures::future::Ready>; + + fn validate_transaction( + &self, + at: &BlockId, + uxt: ExtrinsicFor, + ) -> Self::ValidationFuture { + let nonce = uxt.transfer().nonce; + let from = uxt.transfer().from.clone(); + + match self.block_id_to_number(at) { + Ok(Some(num)) if num > 5 => { + return futures::future::ready( + Ok(Err(InvalidTransaction::Stale.into())) + ) + }, + _ => {}, + } + + futures::future::ready( + Ok(Ok(ValidTransaction { + priority: 4, + requires: if nonce > 1 && self.nonce_dependant { + vec![to_tag(nonce-1, from.clone())] + } else { vec![] }, + provides: vec![to_tag(nonce, from)], + longevity: 10, + propagate: true, + })) + ) + } + + fn block_id_to_number( + &self, + at: &BlockId, + ) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(*num), + BlockId::Hash(_) => None, + }) + } + + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), + BlockId::Hash(_) => None, + }) + } + + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { + let encoded = uxt.encode(); + (blake2_256(&encoded).into(), encoded.len()) + } +} + +fn uxt(transfer: Transfer) -> Extrinsic { + Extrinsic::Transfer(transfer, Default::default()) +} + +fn bench_configured(pool: Pool, number: u64) { + let mut futures = Vec::new(); + let mut tags = Vec::new(); + + for nonce in 1..=number { + let xt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce, + }); + + tags.push(to_tag(nonce, AccountId::from_h256(H256::from_low_u64_be(1)))); + futures.push(pool.submit_one(&BlockId::Number(1), xt)); + } + + let res = block_on(futures::future::join_all(futures.into_iter())); + assert!(res.iter().all(Result::is_ok)); + + assert_eq!(pool.status().future, 0); + assert_eq!(pool.status().ready, number as usize); + + // Prune all transactions. + let block_num = 6; + block_on(pool.prune_tags( + &BlockId::Number(block_num), + tags, + vec![], + )).expect("Prune failed"); + + // pool is empty + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); +} + +fn benchmark_main(c: &mut Criterion) { + + c.bench_function("sequential 50 tx", |b| { + b.iter(|| { + bench_configured(Pool::new(Default::default(), TestApi::new_dependant()), 50); + }); + }); + + c.bench_function("random 100 tx", |b| { + b.iter(|| { + bench_configured(Pool::new(Default::default(), TestApi::default()), 100); + }); + }); +} + +criterion_group!(benches, benchmark_main); +criterion_main!(benches); diff --git a/substrate/core/transaction-pool/graph/src/pool.rs b/substrate/core/transaction-pool/graph/src/pool.rs index 621aeabda8..97244f1cec 100644 --- a/substrate/core/transaction-pool/graph/src/pool.rs +++ b/substrate/core/transaction-pool/graph/src/pool.rs @@ -475,7 +475,6 @@ mod tests { Pool::new(Default::default(), TestApi::default()) } - #[test] fn should_validate_and_import_transaction() { // given