1mod common;
20mod construct;
21#[macro_use]
22mod core;
23mod generator;
24mod import;
25mod simple_trie;
26mod state_sizes;
27mod tempdb;
28mod trie;
29mod txpool;
30
31use clap::Parser;
32
33use node_testing::bench::{BlockType, DatabaseType as BenchDataBaseType, KeyTypes};
34
35use crate::{
36 common::SizeType,
37 construct::ConstructionBenchmarkDescription,
38 core::{run_benchmark, Mode as BenchmarkMode},
39 import::ImportBenchmarkDescription,
40 tempdb::DatabaseType,
41 trie::{DatabaseSize, TrieReadBenchmarkDescription, TrieWriteBenchmarkDescription},
42 txpool::PoolBenchmarkDescription,
43};
44
45#[derive(Debug, Parser)]
46#[command(name = "node-bench", about = "Node integration benchmarks")]
47struct Opt {
48 #[arg(short, long)]
52 list: bool,
53
54 #[arg(short, long)]
58 json: bool,
59
60 filter: Option<String>,
64
65 #[arg(long)]
67 transactions: Option<usize>,
68
69 #[arg(short, long, default_value = "regular")]
76 mode: BenchmarkMode,
77}
78
79fn main() {
80 let opt = Opt::parse();
81
82 if !opt.json {
83 sp_tracing::try_init_simple();
84 }
85
86 let mut import_benchmarks = Vec::new();
87
88 for size in [
89 SizeType::Empty,
90 SizeType::Small,
91 SizeType::Medium,
92 SizeType::Large,
93 SizeType::Full,
94 SizeType::Custom(opt.transactions.unwrap_or(0)),
95 ] {
96 for block_type in [
97 BlockType::RandomTransfersKeepAlive,
98 BlockType::RandomTransfersReaping,
99 BlockType::Noop,
100 ] {
101 for database_type in [BenchDataBaseType::RocksDb, BenchDataBaseType::ParityDb] {
102 import_benchmarks.push((size, block_type, database_type));
103 }
104 }
105 }
106
107 let benchmarks = matrix!(
108 (size, block_type, database_type) in import_benchmarks.into_iter() =>
109 ImportBenchmarkDescription {
110 key_types: KeyTypes::Sr25519,
111 size,
112 block_type,
113 database_type,
114 },
115 (size, db_type) in
116 [
117 DatabaseSize::Empty, DatabaseSize::Smallest, DatabaseSize::Small,
118 DatabaseSize::Medium, DatabaseSize::Large, DatabaseSize::Huge,
119 ]
120 .iter().flat_map(|size|
121 [
122 DatabaseType::RocksDb, DatabaseType::ParityDb
123 ]
124 .iter().map(move |db_type| (size, db_type)))
125 => TrieReadBenchmarkDescription { database_size: *size, database_type: *db_type },
126 (size, db_type) in
127 [
128 DatabaseSize::Empty, DatabaseSize::Smallest, DatabaseSize::Small,
129 DatabaseSize::Medium, DatabaseSize::Large, DatabaseSize::Huge,
130 ]
131 .iter().flat_map(|size|
132 [
133 DatabaseType::RocksDb, DatabaseType::ParityDb
134 ]
135 .iter().map(move |db_type| (size, db_type)))
136 => TrieWriteBenchmarkDescription { database_size: *size, database_type: *db_type },
137 ConstructionBenchmarkDescription {
138 key_types: KeyTypes::Sr25519,
139 block_type: BlockType::RandomTransfersKeepAlive,
140 size: SizeType::Medium,
141 database_type: BenchDataBaseType::RocksDb,
142 },
143 ConstructionBenchmarkDescription {
144 key_types: KeyTypes::Sr25519,
145 block_type: BlockType::RandomTransfersKeepAlive,
146 size: SizeType::Large,
147 database_type: BenchDataBaseType::RocksDb,
148 },
149 PoolBenchmarkDescription { database_type: BenchDataBaseType::RocksDb },
150 );
151
152 if opt.list {
153 println!("Available benchmarks:");
154 if let Some(filter) = opt.filter.as_ref() {
155 println!("\t(filtered by \"{}\")", filter);
156 }
157 for benchmark in benchmarks.iter() {
158 if opt.filter.as_ref().map(|f| benchmark.path().has(f)).unwrap_or(true) {
159 println!("{}: {}", benchmark.name(), benchmark.path().full())
160 }
161 }
162 return
163 }
164
165 let mut results = Vec::new();
166 for benchmark in benchmarks {
167 if opt.filter.as_ref().map(|f| benchmark.path().has(f)).unwrap_or(true) {
168 log::info!("Starting {}", benchmark.name());
169 let result = run_benchmark(benchmark, opt.mode);
170 log::info!("{}", result);
171
172 results.push(result);
173 }
174 }
175
176 if results.is_empty() {
177 eprintln!("No benchmark was found for query");
178 std::process::exit(1);
179 }
180
181 if opt.json {
182 let json_result: String =
183 serde_json::to_string(&results).expect("Failed to construct json");
184 println!("{}", json_result);
185 }
186}