1use 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}