referrerpolicy=no-referrer-when-downgrade

node_bench/
import.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Block import benchmark.
20//!
21//! This benchmark is expected to measure block import operation of
22//! some more or less full block.
23//!
24//! As we also want to protect against cold-cache attacks, this
25//! benchmark should not rely on any caching (except those that
26//! DO NOT depend on user input). Thus block generation should be
27//! based on randomized operation.
28//!
29//! This is supposed to be very simple benchmark and is not subject
30//! to much configuring - just block full of randomized transactions.
31//! It is not supposed to measure runtime modules weight correctness
32
33use std::borrow::Cow;
34
35use node_primitives::Block;
36use node_testing::bench::{BenchDb, BlockType, DatabaseType, KeyTypes};
37use sc_client_api::backend::Backend;
38use sp_state_machine::InspectState;
39
40use crate::{
41	common::SizeType,
42	core::{self, Mode, Path},
43};
44
45pub struct ImportBenchmarkDescription {
46	pub key_types: KeyTypes,
47	pub block_type: BlockType,
48	pub size: SizeType,
49	pub database_type: DatabaseType,
50}
51
52pub struct ImportBenchmark {
53	database: BenchDb,
54	block: Block,
55	block_type: BlockType,
56}
57
58impl core::BenchmarkDescription for ImportBenchmarkDescription {
59	fn path(&self) -> Path {
60		let mut path = Path::new(&["node", "import"]);
61
62		match self.key_types {
63			KeyTypes::Sr25519 => path.push("sr25519"),
64			KeyTypes::Ed25519 => path.push("ed25519"),
65		}
66
67		match self.block_type {
68			BlockType::RandomTransfersKeepAlive => path.push("transfer_keep_alive"),
69			BlockType::RandomTransfersReaping => path.push("transfer_reaping"),
70			BlockType::Noop => path.push("noop"),
71		}
72
73		match self.database_type {
74			DatabaseType::RocksDb => path.push("rocksdb"),
75			DatabaseType::ParityDb => path.push("paritydb"),
76		}
77
78		path.push(&format!("{}", self.size));
79
80		path
81	}
82
83	fn setup(self: Box<Self>) -> Box<dyn core::Benchmark> {
84		let mut bench_db = BenchDb::with_key_types(self.database_type, 50_000, self.key_types);
85		let block = bench_db.generate_block(self.block_type.to_content(self.size.transactions()));
86		Box::new(ImportBenchmark { database: bench_db, block_type: self.block_type, block })
87	}
88
89	fn name(&self) -> Cow<'static, str> {
90		format!(
91			"Block import ({:?}/{}, {:?} backend)",
92			self.block_type, self.size, self.database_type,
93		)
94		.into()
95	}
96}
97
98impl core::Benchmark for ImportBenchmark {
99	fn run(&mut self, mode: Mode) -> std::time::Duration {
100		let mut context = self.database.create_context();
101
102		let _ = context
103			.client
104			.runtime_version_at(context.client.chain_info().genesis_hash)
105			.expect("Failed to get runtime version")
106			.spec_version;
107
108		if mode == Mode::Profile {
109			std::thread::park_timeout(std::time::Duration::from_secs(3));
110		}
111
112		let start = std::time::Instant::now();
113		context.import_block(self.block.clone());
114		let elapsed = start.elapsed();
115
116		// Sanity checks.
117		context
118			.client
119			.state_at(self.block.header.hash())
120			.expect("state_at failed for block#1")
121			.inspect_state(|| {
122				match self.block_type {
123					BlockType::RandomTransfersKeepAlive => {
124						// should be 9 per signed extrinsic + 1 per unsigned
125						// we have 2 unsigned (timestamp and glutton bloat) while the rest are
126						// signed in the block.
127						// those 9 events per signed are:
128						//    - transaction paid for the transaction payment
129						//    - withdraw (Balances::Withdraw) for charging the transaction fee
130						//    - new account (System::NewAccount) as we always transfer fund to
131						//      non-existent account
132						//    - endowed (Balances::Endowed) for this new account
133						//    - issued (Balances::Issued) as total issuance is increased
134						//    - successful transfer (Event::Transfer) for this transfer operation
135						//    - 2x deposit (Balances::Deposit and Treasury::Deposit) for depositing
136						//      the transaction fee into the treasury
137						//    - extrinsic success
138						assert_eq!(
139							kitchensink_runtime::System::events().len(),
140							(self.block.extrinsics.len() - 2) * 9 + 2,
141						);
142					},
143					BlockType::Noop => {
144						assert_eq!(
145							kitchensink_runtime::System::events().len(),
146							// should be 2 per signed extrinsic + 1 per unsigned
147							// we have 2 unsigned and the rest are signed in the block
148							// those 2 events per signed are:
149							//    - deposit event for charging transaction fee
150							//    - extrinsic success
151							// +3 Bags List events from on_idle hook
152							(self.block.extrinsics.len() - 2) * 2 + 2 + 3,
153						);
154					},
155					_ => {},
156				}
157			});
158
159		if mode == Mode::Profile {
160			std::thread::park_timeout(std::time::Duration::from_secs(1));
161		}
162
163		log::info!(
164			target: "bench-logistics",
165			"imported block with {} tx, took: {:#?}",
166			self.block.extrinsics.len(),
167			elapsed,
168		);
169
170		log::info!(
171			target: "bench-logistics",
172			"usage info: {}",
173			context.backend.usage_info()
174				.expect("RocksDB backend always provides usage info!"),
175		);
176
177		elapsed
178	}
179}