mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 06:27:58 +00:00
Block production integration benchmark (#6468)
* proposer benchmark * update cargo.lock
This commit is contained in:
@@ -152,20 +152,12 @@ impl BlockType {
|
||||
}
|
||||
|
||||
/// Content of the generated block.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BlockContent {
|
||||
block_type: BlockType,
|
||||
size: Option<usize>,
|
||||
}
|
||||
|
||||
impl BlockContent {
|
||||
fn iter_while(&self, mut f: impl FnMut(usize) -> bool) {
|
||||
match self.size {
|
||||
Some(v) => { for i in 0..v { if !f(i) { break; }}}
|
||||
None => { for i in 0.. { if !f(i) { break; }}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Type of backend database.
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum DatabaseType {
|
||||
@@ -219,6 +211,93 @@ impl CloneableSpawn for TaskExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator for block content.
|
||||
pub struct BlockContentIterator<'a> {
|
||||
iteration: usize,
|
||||
content: BlockContent,
|
||||
runtime_version: sc_executor::RuntimeVersion,
|
||||
genesis_hash: node_primitives::Hash,
|
||||
keyring: &'a BenchKeyring,
|
||||
}
|
||||
|
||||
impl<'a> BlockContentIterator<'a> {
|
||||
fn new(content: BlockContent, keyring: &'a BenchKeyring, client: &Client) -> Self {
|
||||
let runtime_version = client.runtime_version_at(&BlockId::number(0))
|
||||
.expect("There should be runtime version at 0");
|
||||
|
||||
let genesis_hash = client.block_hash(Zero::zero())
|
||||
.expect("Database error?")
|
||||
.expect("Genesis block always exists; qed")
|
||||
.into();
|
||||
|
||||
BlockContentIterator {
|
||||
iteration: 0,
|
||||
content,
|
||||
keyring,
|
||||
runtime_version,
|
||||
genesis_hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for BlockContentIterator<'a> {
|
||||
type Item = OpaqueExtrinsic;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.content.size.map(|size| size <= self.iteration).unwrap_or(false) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let sender = self.keyring.at(self.iteration);
|
||||
let receiver = get_account_id_from_seed::<sr25519::Public>(
|
||||
&format!("random-user//{}", self.iteration)
|
||||
);
|
||||
|
||||
let signed = self.keyring.sign(
|
||||
CheckedExtrinsic {
|
||||
signed: Some((sender, signed_extra(0, node_runtime::ExistentialDeposit::get() + 1))),
|
||||
function: match self.content.block_type {
|
||||
BlockType::RandomTransfersKeepAlive => {
|
||||
Call::Balances(
|
||||
BalancesCall::transfer_keep_alive(
|
||||
pallet_indices::address::Address::Id(receiver),
|
||||
node_runtime::ExistentialDeposit::get() + 1,
|
||||
)
|
||||
)
|
||||
},
|
||||
BlockType::RandomTransfersReaping => {
|
||||
Call::Balances(
|
||||
BalancesCall::transfer(
|
||||
pallet_indices::address::Address::Id(receiver),
|
||||
// Transfer so that ending balance would be 1 less than existential deposit
|
||||
// so that we kill the sender account.
|
||||
100*DOLLARS - (node_runtime::ExistentialDeposit::get() - 1),
|
||||
)
|
||||
)
|
||||
},
|
||||
BlockType::Noop => {
|
||||
Call::System(
|
||||
SystemCall::remark(Vec::new())
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
self.runtime_version.spec_version,
|
||||
self.runtime_version.transaction_version,
|
||||
self.genesis_hash.into(),
|
||||
);
|
||||
|
||||
let encoded = Encode::encode(&signed);
|
||||
|
||||
let opaque = OpaqueExtrinsic::decode(&mut &encoded[..])
|
||||
.expect("Failed to decode opaque");
|
||||
|
||||
self.iteration += 1;
|
||||
|
||||
Some(opaque)
|
||||
}
|
||||
}
|
||||
|
||||
impl BenchDb {
|
||||
/// New immutable benchmarking database.
|
||||
///
|
||||
@@ -288,8 +367,33 @@ impl BenchDb {
|
||||
(client, backend)
|
||||
}
|
||||
|
||||
/// Generate new block using this database.
|
||||
pub fn generate_block(&mut self, content: BlockContent) -> Block {
|
||||
/// Generate list of required inherents.
|
||||
///
|
||||
/// Uses already instantiated Client.
|
||||
pub fn generate_inherents(&mut self, client: &Client) -> Vec<OpaqueExtrinsic> {
|
||||
let mut inherent_data = InherentData::new();
|
||||
let timestamp = 1 * MinimumPeriod::get();
|
||||
|
||||
inherent_data.put_data(sp_timestamp::INHERENT_IDENTIFIER, ×tamp)
|
||||
.expect("Put timestamp failed");
|
||||
inherent_data.put_data(sp_finality_tracker::INHERENT_IDENTIFIER, &0)
|
||||
.expect("Put finality tracker failed");
|
||||
|
||||
client.runtime_api()
|
||||
.inherent_extrinsics_with_context(
|
||||
&BlockId::number(0),
|
||||
ExecutionContext::BlockConstruction,
|
||||
inherent_data,
|
||||
).expect("Get inherents failed")
|
||||
}
|
||||
|
||||
/// Iterate over some block content with transaction signed using this database keyring.
|
||||
pub fn block_content(&self, content: BlockContent, client: &Client) -> BlockContentIterator {
|
||||
BlockContentIterator::new(content, &self.keyring, client)
|
||||
}
|
||||
|
||||
/// Get cliet for this database operations.
|
||||
pub fn client(&mut self) -> Client {
|
||||
let (client, _backend) = Self::bench_client(
|
||||
self.database_type,
|
||||
self.directory_guard.path(),
|
||||
@@ -297,92 +401,33 @@ impl BenchDb {
|
||||
&self.keyring,
|
||||
);
|
||||
|
||||
let runtime_version = client.runtime_version_at(&BlockId::number(0))
|
||||
.expect("There should be runtime version at 0");
|
||||
client
|
||||
}
|
||||
|
||||
let genesis_hash = client.block_hash(Zero::zero())
|
||||
.expect("Database error?")
|
||||
.expect("Genesis block always exists; qed")
|
||||
.into();
|
||||
/// Generate new block using this database.
|
||||
pub fn generate_block(&mut self, content: BlockContent) -> Block {
|
||||
let client = self.client();
|
||||
|
||||
let mut block = client
|
||||
.new_block(Default::default())
|
||||
.expect("Block creation failed");
|
||||
|
||||
let timestamp = 1 * MinimumPeriod::get();
|
||||
|
||||
let mut inherent_data = InherentData::new();
|
||||
inherent_data.put_data(sp_timestamp::INHERENT_IDENTIFIER, ×tamp)
|
||||
.expect("Put timestamp failed");
|
||||
inherent_data.put_data(sp_finality_tracker::INHERENT_IDENTIFIER, &0)
|
||||
.expect("Put finality tracker failed");
|
||||
|
||||
for extrinsic in client.runtime_api()
|
||||
.inherent_extrinsics_with_context(
|
||||
&BlockId::number(0),
|
||||
ExecutionContext::BlockConstruction,
|
||||
inherent_data,
|
||||
).expect("Get inherents failed")
|
||||
{
|
||||
for extrinsic in self.generate_inherents(&client) {
|
||||
block.push(extrinsic).expect("Push inherent failed");
|
||||
}
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
content.iter_while(|iteration| {
|
||||
let sender = self.keyring.at(iteration);
|
||||
let receiver = get_account_id_from_seed::<sr25519::Public>(
|
||||
&format!("random-user//{}", iteration)
|
||||
);
|
||||
|
||||
let signed = self.keyring.sign(
|
||||
CheckedExtrinsic {
|
||||
signed: Some((sender, signed_extra(0, node_runtime::ExistentialDeposit::get() + 1))),
|
||||
function: match content.block_type {
|
||||
BlockType::RandomTransfersKeepAlive => {
|
||||
Call::Balances(
|
||||
BalancesCall::transfer_keep_alive(
|
||||
pallet_indices::address::Address::Id(receiver),
|
||||
node_runtime::ExistentialDeposit::get() + 1,
|
||||
)
|
||||
)
|
||||
},
|
||||
BlockType::RandomTransfersReaping => {
|
||||
Call::Balances(
|
||||
BalancesCall::transfer(
|
||||
pallet_indices::address::Address::Id(receiver),
|
||||
// Transfer so that ending balance would be 1 less than existential deposit
|
||||
// so that we kill the sender account.
|
||||
100*DOLLARS - (node_runtime::ExistentialDeposit::get() - 1),
|
||||
)
|
||||
)
|
||||
},
|
||||
BlockType::Noop => {
|
||||
Call::System(
|
||||
SystemCall::remark(Vec::new())
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
runtime_version.spec_version,
|
||||
runtime_version.transaction_version,
|
||||
genesis_hash,
|
||||
);
|
||||
|
||||
let encoded = Encode::encode(&signed);
|
||||
|
||||
let opaque = OpaqueExtrinsic::decode(&mut &encoded[..])
|
||||
.expect("Failed to decode opaque");
|
||||
|
||||
for opaque in self.block_content(content, &client) {
|
||||
match block.push(opaque) {
|
||||
Err(sp_blockchain::Error::ApplyExtrinsicFailed(
|
||||
sp_blockchain::ApplyExtrinsicFailed::Validity(e)
|
||||
)) if e.exhausted_resources() => {
|
||||
return false;
|
||||
break;
|
||||
},
|
||||
Err(err) => panic!("Error pushing transaction: {:?}", err),
|
||||
Ok(_) => true,
|
||||
Ok(_) => {},
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let block = block.build().expect("Block build failed").block;
|
||||
|
||||
@@ -411,7 +456,7 @@ impl BenchDb {
|
||||
);
|
||||
|
||||
BenchContext {
|
||||
client, backend, db_guard: directory_guard,
|
||||
client: Arc::new(client), backend, db_guard: directory_guard,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -543,7 +588,7 @@ impl Guard {
|
||||
/// Benchmarking/test context holding instantiated client and backend references.
|
||||
pub struct BenchContext {
|
||||
/// Node client.
|
||||
pub client: Client,
|
||||
pub client: Arc<Client>,
|
||||
/// Node backend.
|
||||
pub backend: Arc<Backend>,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user