frame_benchmarking_cli/pallet/mod.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18mod command;
19mod logging;
20mod types;
21mod writer;
22
23use crate::shared::HostInfoParams;
24use clap::ValueEnum;
25use frame_support::Serialize;
26use sc_cli::{
27 WasmExecutionMethod, WasmtimeInstantiationStrategy, DEFAULT_WASMTIME_INSTANTIATION_STRATEGY,
28 DEFAULT_WASM_EXECUTION_METHOD,
29};
30use std::{fmt::Debug, path::PathBuf};
31
32/// Logging target
33const LOG_TARGET: &'static str = "frame::benchmark::pallet";
34
35// Add a more relaxed parsing for pallet names by allowing pallet directory names with `-` to be
36// used like crate names with `_`
37fn parse_pallet_name(pallet: &str) -> std::result::Result<String, String> {
38 Ok(pallet.replace("-", "_"))
39}
40
41/// List options for available benchmarks.
42#[derive(Debug, Clone, Copy, ValueEnum)]
43pub enum ListOutput {
44 /// List all available pallets and extrinsics.
45 All,
46 /// List all available pallets only.
47 Pallets,
48}
49
50/// Benchmark the extrinsic weight of FRAME Pallets.
51#[derive(Debug, clap::Parser)]
52pub struct PalletCmd {
53 /// Select a FRAME Pallets to benchmark, or `*` for all (in which case `extrinsic` must be
54 /// `*`).
55 #[arg(short, long, alias = "pallet", num_args = 1.., value_delimiter = ',', value_parser = parse_pallet_name, required_unless_present_any = ["list", "json_input", "all"], default_value_if("all", "true", Some("*".into())))]
56 pub pallets: Vec<String>,
57
58 /// Select an extrinsic inside the pallet to benchmark, or `*` or 'all' for all.
59 #[arg(short, long, required_unless_present_any = ["list", "json_input", "all"], default_value_if("all", "true", Some("*".into())))]
60 pub extrinsic: Option<String>,
61
62 /// Comma separated list of pallets that should be excluded from the benchmark.
63 #[arg(long, value_parser, num_args = 1.., value_delimiter = ',')]
64 pub exclude_pallets: Vec<String>,
65
66 /// Comma separated list of `pallet::extrinsic` combinations that should not be run.
67 ///
68 /// Example: `frame_system::remark,pallet_balances::transfer_keep_alive`
69 #[arg(long, value_parser, num_args = 1.., value_delimiter = ',')]
70 pub exclude_extrinsics: Vec<String>,
71
72 /// Run benchmarks for all pallets and extrinsics.
73 ///
74 /// This is equivalent to running `--pallet * --extrinsic *`.
75 #[arg(long)]
76 pub all: bool,
77
78 /// Select how many samples we should take across the variable components.
79 #[arg(short, long, default_value_t = 50)]
80 pub steps: u32,
81
82 /// Indicates lowest values for each of the component ranges.
83 #[arg(long = "low", value_delimiter = ',')]
84 pub lowest_range_values: Vec<u32>,
85
86 /// Indicates highest values for each of the component ranges.
87 #[arg(long = "high", value_delimiter = ',')]
88 pub highest_range_values: Vec<u32>,
89
90 /// Minimum number of repetitions of this benchmark should run from within the wasm.
91 ///
92 /// It may run more often than this to reach its `min_duration`.
93 #[arg(short, long, default_value_t = 20)]
94 pub repeat: u32,
95
96 /// DEPRECATED: Please remove usage.
97 #[arg(long)]
98 pub external_repeat: Option<u32>,
99
100 /// Minimum duration in seconds for each benchmark.
101 ///
102 /// Can be set to 0 to disable the feature and solely rely on the `repeat` parameter.
103 #[arg(long, default_value_t = 10)]
104 pub min_duration: u64,
105
106 /// Print the raw results in JSON format.
107 #[arg(long = "json")]
108 pub json_output: bool,
109
110 /// Write the raw results in JSON format into the given file.
111 #[arg(long, conflicts_with = "json_output")]
112 pub json_file: Option<PathBuf>,
113
114 /// Don't print the median-slopes linear regression analysis.
115 #[arg(long)]
116 pub no_median_slopes: bool,
117
118 /// Don't print the min-squares linear regression analysis.
119 #[arg(long)]
120 pub no_min_squares: bool,
121
122 /// Output the benchmarks to a Rust file at the given path.
123 #[arg(long)]
124 pub output: Option<PathBuf>,
125
126 /// Add a header file to your outputted benchmarks.
127 #[arg(long)]
128 pub header: Option<PathBuf>,
129
130 /// Path to Handlebars template file used for outputting benchmark results. (Optional)
131 #[arg(long)]
132 pub template: Option<PathBuf>,
133
134 #[allow(missing_docs)]
135 #[clap(flatten)]
136 pub hostinfo_params: HostInfoParams,
137
138 /// Which analysis function to use when outputting benchmarks:
139 /// * min-squares (default)
140 /// * median-slopes
141 /// * max (max of min squares and median slopes for each value)
142 #[arg(long)]
143 pub output_analysis: Option<String>,
144
145 /// Which analysis function to use when analyzing measured proof sizes.
146 #[arg(long, default_value("median-slopes"))]
147 pub output_pov_analysis: Option<String>,
148
149 /// The PoV estimation mode of a benchmark if no `pov_mode` attribute is present.
150 #[arg(long, default_value("max-encoded-len"), value_enum)]
151 pub default_pov_mode: command::PovEstimationMode,
152
153 /// Ignore the error when PoV modes reference unknown storage items or pallets.
154 #[arg(long)]
155 pub ignore_unknown_pov_mode: bool,
156
157 /// Set the heap pages while running benchmarks. If not set, the default value from the client
158 /// is used.
159 #[arg(long)]
160 pub heap_pages: Option<u64>,
161
162 /// Disable verification logic when running benchmarks.
163 #[arg(long)]
164 pub no_verify: bool,
165
166 /// Display and run extra benchmarks that would otherwise not be needed for weight
167 /// construction.
168 #[arg(long)]
169 pub extra: bool,
170
171 #[allow(missing_docs)]
172 #[clap(flatten)]
173 pub shared_params: sc_cli::SharedParams,
174
175 /// Method for executing Wasm runtime code.
176 #[arg(
177 long = "wasm-execution",
178 value_name = "METHOD",
179 value_enum,
180 ignore_case = true,
181 default_value_t = DEFAULT_WASM_EXECUTION_METHOD,
182 )]
183 pub wasm_method: WasmExecutionMethod,
184
185 /// The WASM instantiation method to use.
186 ///
187 /// Only has an effect when `wasm-execution` is set to `compiled`.
188 #[arg(
189 long = "wasm-instantiation-strategy",
190 value_name = "STRATEGY",
191 default_value_t = DEFAULT_WASMTIME_INSTANTIATION_STRATEGY,
192 value_enum,
193 )]
194 pub wasmtime_instantiation_strategy: WasmtimeInstantiationStrategy,
195
196 /// Optional runtime blob to use instead of the one from the genesis config.
197 #[arg(long, conflicts_with = "chain", required_if_eq("genesis_builder", "runtime"))]
198 pub runtime: Option<PathBuf>,
199
200 /// Set the runtime log level.
201 ///
202 /// This will overwrite the `RUNTIME_LOG` environment variable. If neither is set, the CLI
203 /// default set by `RUST_LOG` setting is used.
204 #[arg(long)]
205 pub runtime_log: Option<String>,
206
207 /// Do not fail if there are unknown but also unused host functions in the runtime.
208 #[arg(long)]
209 pub allow_missing_host_functions: bool,
210
211 /// How to construct the genesis state.
212 ///
213 /// Uses `GenesisBuilderPolicy::Spec` by default.
214 #[arg(long, value_enum, alias = "genesis-builder-policy")]
215 pub genesis_builder: Option<GenesisBuilderPolicy>,
216
217 /// The preset that we expect to find in the GenesisBuilder runtime API.
218 ///
219 /// This can be useful when a runtime has a dedicated benchmarking preset instead of using the
220 /// default one.
221 #[arg(long, default_value = sp_genesis_builder::DEV_RUNTIME_PRESET)]
222 pub genesis_builder_preset: String,
223
224 /// DEPRECATED: This argument has no effect.
225 #[arg(long = "execution")]
226 pub execution: Option<String>,
227
228 /// Limit the memory the database cache can use.
229 #[arg(long = "db-cache", value_name = "MiB", default_value_t = 1024)]
230 pub database_cache_size: u32,
231
232 /// List and print available benchmarks in a csv-friendly format.
233 ///
234 /// NOTE: `num_args` and `require_equals` are required to allow `--list`
235 #[arg(long, value_enum, ignore_case = true, num_args = 0..=1, require_equals = true, default_missing_value("All"))]
236 pub list: Option<ListOutput>,
237
238 /// Don't include csv header when listing benchmarks.
239 #[arg(long, requires("list"))]
240 pub no_csv_header: bool,
241
242 /// If enabled, the storage info is not displayed in the output next to the analysis.
243 ///
244 /// This is independent of the storage info appearing in the *output file*. Use a Handlebar
245 /// template for that purpose.
246 #[arg(long)]
247 pub no_storage_info: bool,
248
249 /// The assumed default maximum size of any `StorageMap`.
250 ///
251 /// When the maximum size of a map is not defined by the runtime developer,
252 /// this value is used as a worst case scenario. It will affect the calculated worst case
253 /// PoV size for accessing a value in a map, since the PoV will need to include the trie
254 /// nodes down to the underlying value.
255 #[clap(long = "map-size", default_value = "1000000")]
256 pub worst_case_map_values: u32,
257
258 /// Adjust the PoV estimation by adding additional trie layers to it.
259 ///
260 /// This should be set to `log16(n)` where `n` is the number of top-level storage items in the
261 /// runtime, eg. `StorageMap`s and `StorageValue`s. A value of 2 to 3 is usually sufficient.
262 /// Each layer will result in an additional 495 bytes PoV per distinct top-level access.
263 /// Therefore multiple `StorageMap` accesses only suffer from this increase once. The exact
264 /// number of storage items depends on the runtime and the deployed pallets.
265 #[clap(long, default_value = "2")]
266 pub additional_trie_layers: u8,
267
268 /// A path to a `.json` file with existing benchmark results generated with `--json` or
269 /// `--json-file`. When specified the benchmarks are not actually executed, and the data for
270 /// the analysis is read from this file.
271 #[arg(long)]
272 pub json_input: Option<PathBuf>,
273
274 /// Allow overwriting a single file with multiple results.
275 ///
276 /// This exists only to restore legacy behaviour. It should never actually be needed.
277 #[arg(long)]
278 pub unsafe_overwrite_results: bool,
279
280 /// Do not print a summary at the end of the run.
281 ///
282 /// These summaries can be very long when benchmarking multiple pallets at once. For CI
283 /// use-cases, this option reduces the noise.
284 #[arg(long)]
285 quiet: bool,
286
287 /// Do not enable proof recording during time benchmarking.
288 ///
289 /// By default, proof recording is enabled during benchmark execution. This can slightly
290 /// inflate the resulting time weights. For parachains using PoV-reclaim, this is typically the
291 /// correct setting. Chains that ignore the proof size dimension of weight (e.g. relay chain,
292 /// solo-chains) can disable proof recording to get more accurate results.
293 #[arg(long)]
294 disable_proof_recording: bool,
295
296 /// Path to a JSON file containing a patch to apply to the genesis state.
297 ///
298 /// This allows modifying the genesis state after it's built but before benchmarking.
299 /// Useful for creating specific testing scenarios like many accounts for benchmarking.
300 #[arg(long)]
301 pub genesis_patch: Option<PathBuf>,
302}
303
304/// How the genesis state for benchmarking should be built.
305#[derive(clap::ValueEnum, Debug, Eq, PartialEq, Clone, Copy, Serialize)]
306#[clap(rename_all = "kebab-case")]
307pub enum GenesisBuilderPolicy {
308 /// Do not provide any genesis state.
309 ///
310 /// Benchmarks are advised to function with this, since they should setup their own required
311 /// state. However, to keep backwards compatibility, this is not the default.
312 None,
313 /// Let the runtime build the genesis state through its `BuildGenesisConfig` runtime API.
314 /// This will use the `development` preset by default.
315 Runtime,
316 /// Use the runtime from the Spec file to build the genesis state.
317 SpecRuntime,
318 /// Use the spec file to build the genesis state. This fails when there is no spec.
319 #[value(alias = "spec")]
320 SpecGenesis,
321}