referrerpolicy=no-referrer-when-downgrade

frame_benchmarking_cli/overhead/
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
18//! Converts a benchmark result into [`TemplateData`] and writes
19//! it into the `weights.hbs` template.
20
21use sc_cli::Result;
22
23use handlebars::Handlebars;
24use log::info;
25use serde::Serialize;
26use std::{env, fs, path::PathBuf};
27
28use crate::{
29	overhead::command::{BenchmarkType, OverheadParams},
30	shared::{Stats, UnderscoreHelper},
31};
32
33static VERSION: &str = env!("CARGO_PKG_VERSION");
34static TEMPLATE: &str = include_str!("./weights.hbs");
35
36/// Data consumed by Handlebar to fill out the `weights.hbs` template.
37#[derive(Serialize, Debug, Clone)]
38pub(crate) struct TemplateData {
39	/// Short name of the benchmark. Can be "block" or "extrinsic".
40	long_name: String,
41	/// Long name of the benchmark. Can be "BlockExecution" or "ExtrinsicBase".
42	short_name: String,
43	/// Name of the runtime. Taken from the chain spec.
44	runtime_name: String,
45	/// Version of the benchmarking CLI used.
46	version: String,
47	/// Date that the template was filled out.
48	date: String,
49	/// Hostname of the machine that executed the benchmarks.
50	hostname: String,
51	/// CPU name of the machine that executed the benchmarks.
52	cpuname: String,
53	/// Header for the generated file.
54	header: String,
55	/// Command line arguments that were passed to the CLI.
56	args: Vec<String>,
57	/// Params of the executed command.
58	params: OverheadParams,
59	/// Stats about the benchmark result.
60	stats: Stats,
61	/// The resulting ref time weight.
62	ref_time: u64,
63	/// The size of the proof weight.
64	proof_size: u64,
65}
66
67impl TemplateData {
68	/// Returns a new [`Self`] from the given params.
69	pub(crate) fn new(
70		t: BenchmarkType,
71		chain_name: &String,
72		params: &OverheadParams,
73		stats: &Stats,
74		proof_size: u64,
75	) -> Result<Self> {
76		let ref_time = params.weight.calc_weight(stats)?;
77		let header = params
78			.header
79			.as_ref()
80			.map(|p| std::fs::read_to_string(p))
81			.transpose()?
82			.unwrap_or_default();
83
84		Ok(TemplateData {
85			short_name: t.short_name().into(),
86			long_name: t.long_name().into(),
87			runtime_name: chain_name.to_owned(),
88			version: VERSION.into(),
89			date: chrono::Utc::now().format("%Y-%m-%d (Y/M/D)").to_string(),
90			hostname: params.hostinfo.hostname(),
91			cpuname: params.hostinfo.cpuname(),
92			header,
93			args: env::args().collect::<Vec<String>>(),
94			params: params.clone(),
95			stats: stats.clone(),
96			ref_time,
97			proof_size,
98		})
99	}
100
101	/// Fill out the `weights.hbs` HBS template with its own data.
102	/// Writes the result to `path` which can be a directory or a file.
103	pub fn write(&self, path: &Option<PathBuf>) -> Result<()> {
104		let mut handlebars = Handlebars::new();
105		// Format large integers with underscores.
106		handlebars.register_helper("underscore", Box::new(UnderscoreHelper));
107		// Don't HTML escape any characters.
108		handlebars.register_escape_fn(|s| -> String { s.to_string() });
109
110		let out_path = self.build_path(path)?;
111		let mut fd = fs::File::create(&out_path)?;
112		info!("Writing weights to {:?}", fs::canonicalize(&out_path)?);
113		handlebars
114			.render_template_to_write(TEMPLATE, &self, &mut fd)
115			.map_err(|e| format!("HBS template write: {:?}", e).into())
116	}
117
118	/// Build a path for the weight file.
119	fn build_path(&self, weight_out: &Option<PathBuf>) -> Result<PathBuf> {
120		let mut path = weight_out.clone().unwrap_or_else(|| PathBuf::from("."));
121
122		if !path.is_dir() {
123			return Err("Need directory as --weight-path".into())
124		}
125		path.push(format!("{}_weights.rs", self.short_name));
126		Ok(path)
127	}
128}