referrerpolicy=no-referrer-when-downgrade

frame_benchmarking_cli/storage/
template.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
18use sc_cli::Result;
19use sc_service::Configuration;
20
21use log::info;
22use serde::Serialize;
23use std::{env, fs, path::PathBuf};
24
25use super::cmd::StorageParams;
26use crate::shared::{Stats, UnderscoreHelper};
27
28static VERSION: &str = env!("CARGO_PKG_VERSION");
29static TEMPLATE: &str = include_str!("./weights.hbs");
30
31/// Data consumed by Handlebar to fill out the `weights.hbs` template.
32#[derive(Serialize, Default, Debug, Clone)]
33pub(crate) struct TemplateData {
34	/// Name of the database used.
35	db_name: String,
36	/// Block number that was used.
37	block_number: String,
38	/// Name of the runtime. Taken from the chain spec.
39	runtime_name: String,
40	/// Version of the benchmarking CLI used.
41	version: String,
42	/// Date that the template was filled out.
43	date: String,
44	/// Hostname of the machine that executed the benchmarks.
45	hostname: String,
46	/// CPU name of the machine that executed the benchmarks.
47	cpuname: String,
48	/// Header for the generated file.
49	header: String,
50	/// Command line arguments that were passed to the CLI.
51	args: Vec<String>,
52	/// Storage params of the executed command.
53	params: StorageParams,
54	/// The weight for one `read`.
55	read_weight: u64,
56	/// The weight for one `write`.
57	write_weight: u64,
58	/// Stats about a `read` benchmark. Contains *time* and *value size* stats.
59	/// The *value size* stats are currently not used in the template.
60	read: Option<(Stats, Stats)>,
61	/// Stats about a `write` benchmark. Contains *time* and *value size* stats.
62	/// The *value size* stats are currently not used in the template.
63	write: Option<(Stats, Stats)>,
64}
65
66impl TemplateData {
67	/// Returns a new [`Self`] from the given configuration.
68	pub fn new(cfg: &Configuration, params: &StorageParams) -> Result<Self> {
69		let header = params
70			.header
71			.as_ref()
72			.map(|p| std::fs::read_to_string(p))
73			.transpose()?
74			.unwrap_or_default();
75
76		Ok(TemplateData {
77			db_name: if params.is_validate_block_mode() {
78				String::from("InMemoryDb")
79			} else {
80				format!("{}", cfg.database)
81			},
82			runtime_name: cfg.chain_spec.name().into(),
83			version: VERSION.into(),
84			date: chrono::Utc::now().format("%Y-%m-%d (Y/M/D)").to_string(),
85			hostname: params.hostinfo.hostname(),
86			cpuname: params.hostinfo.cpuname(),
87			header,
88			args: env::args().collect::<Vec<String>>(),
89			params: params.clone(),
90			..Default::default()
91		})
92	}
93
94	/// Sets the stats and calculates the final weights.
95	pub fn set_stats(
96		&mut self,
97		read: Option<(Stats, Stats)>,
98		write: Option<(Stats, Stats)>,
99	) -> Result<()> {
100		if let Some(read) = read {
101			self.read_weight = self.params.weight_params.calc_weight(&read.0)?;
102			self.read = Some(read);
103		}
104		if let Some(write) = write {
105			self.write_weight = self.params.weight_params.calc_weight(&write.0)?;
106			self.write = Some(write);
107		}
108		Ok(())
109	}
110
111	/// Sets the block id that was used.
112	pub fn set_block_number(&mut self, block_number: String) {
113		self.block_number = block_number
114	}
115
116	/// Fills out the `weights.hbs` or specified HBS template with its own data.
117	/// Writes the result to `path` which can be a directory or file.
118	pub fn write(&self, path: &Option<PathBuf>, hbs_template: &Option<PathBuf>) -> Result<()> {
119		let mut handlebars = handlebars::Handlebars::new();
120		// Format large integers with underscore.
121		handlebars.register_helper("underscore", Box::new(UnderscoreHelper));
122		// Don't HTML escape any characters.
123		handlebars.register_escape_fn(|s| -> String { s.to_string() });
124		// Use custom template if provided.
125		let template = match hbs_template {
126			Some(template) if template.is_file() => fs::read_to_string(template)?,
127			Some(_) => return Err("Handlebars template is not a valid file!".into()),
128			None => TEMPLATE.to_string(),
129		};
130
131		let out_path = self.build_path(path);
132		let mut fd = fs::File::create(&out_path)?;
133		info!("Writing weights to {:?}", fs::canonicalize(&out_path)?);
134
135		handlebars
136			.render_template_to_write(&template, &self, &mut fd)
137			.map_err(|e| format!("HBS template write: {:?}", e).into())
138	}
139
140	/// Builds a path for the weight file.
141	fn build_path(&self, weight_out: &Option<PathBuf>) -> PathBuf {
142		let mut path = match weight_out {
143			Some(p) => PathBuf::from(p),
144			None => PathBuf::new(),
145		};
146
147		if path.is_dir() || path.as_os_str().is_empty() {
148			path.push(format!("{}_weights", self.db_name.to_lowercase()));
149			path.set_extension("rs");
150		}
151		path
152	}
153}