Files
arkhe-origin-chain/scripts/bench/origin-weights-template.hbs
T
davidherranandClaude Opus 5 b72650974d feat(bench): regenerar weights deja de ser una promesa y pasa a ser un comando
Durante meses la cabecera de los cinco weights.rs prometia que regenerar
"es mecanico". No lo era: no habia comando, ni plantilla, ni forma de
correrlo. La promesa costo lo que cuestan las promesas sin codigo — al
medir por primera vez, los 19 extrinsics estaban SUBDECLARADOS, los 19.

Tres piezas:

· scripts/bench/regen-weights.sh — construye el WASM con
  runtime-benchmarks y mide los 5 pallets. SKIP_BUILD=1 + WASM=<ruta>
  mide un blob YA construido: es el modo del banco de referencia, donde
  el Pi 5 no compila Substrate sino que recibe el blob que se despliega,
  de modo que el binario medido y el desplegado son el MISMO.

· scripts/bench/origin-weights-template.hbs — emite la forma de la casa
  (trait + SubstrateWeight<T> + impl para ()) y, dentro, un guard
  GENERADO a partir de los benchmarks reales que reprueba cualquier
  proof_size = 0 o ref_time = 0. Generado, no escrito: no puede quedarse
  corto cuando se anada un extrinsic.

· scripts/bench/HEADER.txt — la cabecera que va dentro de cada fichero
  generado, diciendo que un weight es una latencia y que sin su hardware
  y su perfil de potencia no se reproduce.

El script documenta ademas dos cosas medidas hoy que cuestan horas si no
estan escritas: (1) hay que usar frame-omni-bencher 0.15.0, porque la
0.23 trae sp-storage 25 contra el sp-storage 22 de este runtime y
TrackedStorageKey no decodifica al cruzar el FFI — falla con "unexpected
first byte decoding Option", que no se parece a "version equivocada";
(2) el governor ondemand arranca a 1600 MHz y sube a 2400, asi que las
primeras muestras salen ~50% lentas y el weight sale de la rampa.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 10:45:30 -05:00

133 lines
4.9 KiB
Handlebars

{{header}}
//! Weights AUTOGENERADOS para `{{pallet}}` — NO editar a mano.
//!
//! Regenerar: `scripts/bench/regen-weights.sh` (ver ese script para el
//! procedimiento completo y el hardware al que hay que creerle).
//!
//! GENERADO POR SUBSTRATE BENCHMARK CLI VERSION {{version}}
//! FECHA: {{date}}, STEPS: `{{cmd.steps}}`, REPEAT: `{{cmd.repeat}}`
//! HOSTNAME: `{{hostname}}`, CPU: `{{cpuname}}`
//! WASM-EXECUTION: `{{cmd.wasm_execution}}`, DB CACHE: {{cmd.db_cache}}
// Comando ejecutado:
{{#each args as |arg|}}
// {{arg}}
{{/each}}
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use core::marker::PhantomData;
use frame_support::{traits::Get, weights::constants::RocksDbWeight, weights::Weight};
/// Trait de weights para los extrinsics de `{{pallet}}`.
pub trait WeightInfo {
{{#each benchmarks as |benchmark|}}
/// Peso de `{{benchmark.name}}` — MEDIDO sobre el WASM, no estimado a mano.
fn {{benchmark.name~}}
({{~#each benchmark.components as |c|}}{{c.name}}: u32, {{/each~}}) -> Weight;
{{/each}}
}
/// Weights parametrizados por el `DbWeight` real del runtime.
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
{{#each benchmarks as |benchmark|}}
{{#each benchmark.comments as |comment|}}
/// {{comment}}
{{/each}}
{{#each benchmark.component_ranges as |range|}}
/// El rango del componente `{{range.name}}` es `[{{range.min}}, {{range.max}}]`.
{{/each}}
fn {{benchmark.name~}}
(
{{~#each benchmark.components as |c| ~}}
{{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}}
) -> Weight {
// Proof size en bytes:
// Medido: `{{benchmark.base_recorded_proof_size}}`
// Estimado: `{{benchmark.base_calculated_proof_size}}`
// Tiempo minimo de ejecucion: {{underscore benchmark.min_execution_time}}_000 picosegundos.
Weight::from_parts({{underscore benchmark.base_weight}}, 0)
.saturating_add(Weight::from_parts(0, {{benchmark.base_calculated_proof_size}}))
{{#each benchmark.component_weight as |cw|}}
// Error estandar: {{underscore cw.error}}
.saturating_add(Weight::from_parts({{underscore cw.slope}}, 0).saturating_mul({{cw.name}}.into()))
{{/each}}
{{#if (ne benchmark.base_reads "0")}}
.saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}}_u64))
{{/if}}
{{#if (ne benchmark.base_writes "0")}}
.saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}}_u64))
{{/if}}
}
{{/each}}
}
/// Impl para mocks y tests — `RocksDbWeight` directo, sin necesitar `T`.
impl WeightInfo for () {
{{#each benchmarks as |benchmark|}}
fn {{benchmark.name~}}
(
{{~#each benchmark.components as |c| ~}}
{{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}}
) -> Weight {
Weight::from_parts({{underscore benchmark.base_weight}}, 0)
.saturating_add(Weight::from_parts(0, {{benchmark.base_calculated_proof_size}}))
{{#each benchmark.component_weight as |cw|}}
.saturating_add(Weight::from_parts({{underscore cw.slope}}, 0).saturating_mul({{cw.name}}.into()))
{{/each}}
{{#if (ne benchmark.base_reads "0")}}
.saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}}_u64))
{{/if}}
{{#if (ne benchmark.base_writes "0")}}
.saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}}_u64))
{{/if}}
}
{{/each}}
}
#[cfg(test)]
mod guard {
use super::*;
/// NINGUN EXTRINSIC PUEDE DECLARAR `proof_size = 0`.
///
/// El `proof_size` es lo que el block-builder usa para no pasarse del limite
/// de PoV. Un cero no dice «este extrinsic no toca storage»: dice «miento
/// sobre lo que va a ocupar la prueba», y con eso entra en un bloque mucho
/// mas de lo que cabe.
///
/// El test nace de un error propio y de la peor clase: la cabecera de los
/// weights interinos afirmaba que `T::DbWeight` «puebla tanto ref_time como
/// proof_size … cerrando el hueco». Es falso y se comprueba en la fuente —
/// `sp_weights::RuntimeDbWeight` solo tiene los campos `read` y `write`, y
/// `reads(r)` devuelve `Weight::from_parts(read * r, 0)`. Los interinos
/// arreglaron reads/writes y dejaron el proof_size donde estaba: en 0. La
/// afirmacion de haberlo cerrado sobrevivio mas de un mes sin que ninguna
/// lectura la desmintiera; la desmintio una medicion.
///
/// Esta lista la GENERA la plantilla a partir de los benchmarks reales, asi
/// que no puede quedarse corta cuando se anada un extrinsic nuevo.
#[test]
fn ningun_weight_declara_proof_size_cero() {
let casos: &[(&str, Weight)] = &[
{{#each benchmarks as |benchmark|}}
("{{benchmark.name}}", <() as WeightInfo>::{{benchmark.name}}({{#each benchmark.components as |c|}}1, {{/each}})),
{{/each}}
];
for (nombre, w) in casos {
assert!(
w.proof_size() > 0,
"`{nombre}` declara proof_size = 0: miente al block-builder sobre el peso PoV"
);
assert!(
w.ref_time() > 0,
"`{nombre}` declara ref_time = 0: el extrinsic saldria gratis"
);
}
}
}