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;
38
39use crate::{
40	common::SizeType,
41	core::{self, Mode, Path},
42};
43
44pub struct ImportBenchmarkDescription {
45	pub key_types: KeyTypes,
46	pub block_type: BlockType,
47	pub size: SizeType,
48	pub database_type: DatabaseType,
49}
50
51pub struct ImportBenchmark {
52	database: BenchDb,
53	block: Block,
54}
55
56impl core::BenchmarkDescription for ImportBenchmarkDescription {
57	fn path(&self) -> Path {
58		let mut path = Path::new(&["node", "import"]);
59
60		match self.key_types {
61			KeyTypes::Sr25519 => path.push("sr25519"),
62			KeyTypes::Ed25519 => path.push("ed25519"),
63		}
64
65		match self.block_type {
66			BlockType::RandomTransfersKeepAlive => path.push("transfer_keep_alive"),
67			BlockType::RandomTransfersReaping => path.push("transfer_reaping"),
68			BlockType::Noop => path.push("noop"),
69		}
70
71		match self.database_type {
72			DatabaseType::RocksDb => path.push("rocksdb"),
73			DatabaseType::ParityDb => path.push("paritydb"),
74		}
75
76		path.push(&format!("{}", self.size));
77
78		path
79	}
80
81	fn setup(self: Box<Self>) -> Box<dyn core::Benchmark> {
82		let mut bench_db = BenchDb::with_key_types(self.database_type, 50_000, self.key_types);
83		let block = bench_db.generate_block(self.block_type.to_content(self.size.transactions()));
84		Box::new(ImportBenchmark { database: bench_db, block })
85	}
86
87	fn name(&self) -> Cow<'static, str> {
88		format!(
89			"Block import ({:?}/{}, {:?} backend)",
90			self.block_type, self.size, self.database_type,
91		)
92		.into()
93	}
94}
95
96impl core::Benchmark for ImportBenchmark {
97	fn run(&mut self, mode: Mode) -> std::time::Duration {
98		let mut context = self.database.create_context();
99
100		let _ = context
101			.client
102			.runtime_version_at(context.client.chain_info().genesis_hash)
103			.expect("Failed to get runtime version")
104			.spec_version;
105
106		if mode == Mode::Profile {
107			std::thread::park_timeout(std::time::Duration::from_secs(3));
108		}
109
110		let start = std::time::Instant::now();
111		context.import_block(self.block.clone());
112		let elapsed = start.elapsed();
113
114		if mode == Mode::Profile {
115			std::thread::park_timeout(std::time::Duration::from_secs(1));
116		}
117
118		log::info!(
119			target: "bench-logistics",
120			"imported block with {} tx, took: {:#?}",
121			self.block.extrinsics.len(),
122			elapsed,
123		);
124
125		log::info!(
126			target: "bench-logistics",
127			"usage info: {}",
128			context.backend.usage_info()
129				.expect("RocksDB backend always provides usage info!"),
130		);
131
132		elapsed
133	}
134}