pallet_election_provider_multi_block/
benchmarking.rs1use crate::{
19 verifier::{self, Verifier},
20 Config, CurrentPhase, Pallet, Phase, Snapshot,
21};
22use frame_benchmarking::v2::*;
23use frame_election_provider_support::{ElectionDataProvider, ElectionProvider};
24use frame_support::pallet_prelude::*;
25
26const SNAPSHOT_NOT_BIG_ENOUGH: &'static str = "Snapshot page is not full, you should run this \
27benchmark with enough genesis stakers in staking (DataProvider) to fill a page of voters/targets \
28as per VoterSnapshotPerBlock and TargetSnapshotPerBlock. Generate at least \
292 * VoterSnapshotPerBlock) nominators and TargetSnapshotPerBlock validators";
30
31#[benchmarks(where T: crate::signed::Config + crate::unsigned::Config + crate::verifier::Config)]
34mod benchmarks {
35 use super::*;
36
37 #[benchmark(pov_mode = Measured)]
38 fn on_initialize_nothing() -> Result<(), BenchmarkError> {
39 assert_eq!(CurrentPhase::<T>::get(), Phase::Off);
40
41 #[block]
42 {
43 Pallet::<T>::roll_next(true, false);
44 }
45
46 assert_eq!(CurrentPhase::<T>::get(), Phase::Off);
47 Ok(())
48 }
49
50 #[benchmark(pov_mode = Measured)]
51 fn on_initialize_into_snapshot_msp() -> Result<(), BenchmarkError> {
52 assert!(T::Pages::get() >= 2, "this benchmark only works in a runtime with 2 pages or more, set at least `type Pages = 2` for benchmark run");
53
54 #[cfg(test)]
55 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
56 crate::Pallet::<T>::start().unwrap();
57
58 assert_eq!(CurrentPhase::<T>::get(), Phase::Snapshot(T::Pages::get()));
59
60 #[block]
61 {
62 Pallet::<T>::roll_next(true, false);
63 }
64
65 assert_eq!(CurrentPhase::<T>::get(), Phase::Snapshot(T::Pages::get() - 1));
67 assert_eq!(
68 Snapshot::<T>::targets_decode_len().unwrap() as u32,
69 T::TargetSnapshotPerBlock::get(),
70 "{}",
71 SNAPSHOT_NOT_BIG_ENOUGH
72 );
73 assert_eq!(Snapshot::<T>::voters_decode_len(T::Pages::get() - 1), None);
74
75 Ok(())
76 }
77
78 #[benchmark(pov_mode = Measured)]
79 fn on_initialize_into_snapshot_rest() -> Result<(), BenchmarkError> {
80 assert!(T::Pages::get() >= 2, "this benchmark only works in a runtime with 2 pages or more, set at least `type Pages = 2` for benchmark run");
81
82 #[cfg(test)]
83 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
84 crate::Pallet::<T>::start().unwrap();
85
86 Pallet::<T>::roll_until_matches(|| {
88 CurrentPhase::<T>::get() == Phase::Snapshot(T::Pages::get() - 1)
89 });
90
91 assert_eq!(
93 Snapshot::<T>::targets_decode_len().unwrap() as u32,
94 T::TargetSnapshotPerBlock::get()
95 );
96 assert_eq!(Snapshot::<T>::voters_decode_len(T::Pages::get() - 1), None);
98
99 #[block]
101 {
102 Pallet::<T>::roll_next(true, false);
103 }
104
105 assert_eq!(CurrentPhase::<T>::get(), Phase::Snapshot(T::Pages::get() - 2));
107 assert_eq!(
109 Snapshot::<T>::voters_decode_len(T::Pages::get() - 1).unwrap() as u32,
110 T::VoterSnapshotPerBlock::get(),
111 "{}",
112 SNAPSHOT_NOT_BIG_ENOUGH
113 );
114 Ok(())
115 }
116
117 #[benchmark(pov_mode = Measured)]
118 fn on_initialize_into_signed() -> Result<(), BenchmarkError> {
119 #[cfg(test)]
120 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
121 crate::Pallet::<T>::start().unwrap();
122
123 Pallet::<T>::roll_until_before_matches(|| {
124 matches!(CurrentPhase::<T>::get(), Phase::Signed(_))
125 });
126
127 assert_eq!(CurrentPhase::<T>::get(), Phase::Snapshot(0));
128
129 #[block]
130 {
131 Pallet::<T>::roll_next(true, false);
132 }
133
134 assert!(CurrentPhase::<T>::get().is_signed());
135
136 Ok(())
137 }
138
139 #[benchmark(pov_mode = Measured)]
140 fn on_initialize_into_signed_validation() -> Result<(), BenchmarkError> {
141 #[cfg(test)]
142 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
143 crate::Pallet::<T>::start().unwrap();
144
145 Pallet::<T>::roll_until_before_matches(|| {
146 matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_))
147 });
148
149 assert!(CurrentPhase::<T>::get().is_signed());
150
151 #[block]
152 {
153 Pallet::<T>::roll_next(true, false);
154 }
155
156 Ok(())
157 }
158
159 #[benchmark(pov_mode = Measured)]
160 fn on_initialize_into_unsigned() -> Result<(), BenchmarkError> {
161 #[cfg(test)]
162 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
163 crate::Pallet::<T>::start().unwrap();
164
165 Pallet::<T>::roll_until_before_matches(|| {
166 matches!(CurrentPhase::<T>::get(), Phase::Unsigned(_))
167 });
168 assert!(matches!(CurrentPhase::<T>::get(), Phase::SignedValidation(_)));
169
170 #[block]
171 {
172 Pallet::<T>::roll_next(true, false);
173 }
174
175 assert!(matches!(CurrentPhase::<T>::get(), Phase::Unsigned(_)));
176 Ok(())
177 }
178
179 #[benchmark(pov_mode = Measured)]
180 fn export_non_terminal() -> Result<(), BenchmarkError> {
181 #[cfg(test)]
182 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
183 crate::Pallet::<T>::start().unwrap();
184
185 crate::Pallet::<T>::roll_to_signed_and_submit_full_solution()?;
187
188 assert!(T::Verifier::queued_score().is_none());
190 crate::Pallet::<T>::roll_until_matches(|| {
191 matches!(CurrentPhase::<T>::get(), Phase::Unsigned(_))
192 });
193
194 assert!(T::Verifier::queued_score().is_some());
196 assert_eq!(verifier::QueuedSolution::<T>::valid_iter().count() as u32, T::Pages::get());
197
198 crate::Pallet::<T>::roll_until_matches(|| CurrentPhase::<T>::get().is_done());
200
201 #[block]
202 {
203 T::DataProvider::fetch_page(T::Pages::get() - 1);
206 }
207
208 assert_eq!(CurrentPhase::<T>::get(), Phase::Export(T::Pages::get() - 2));
210
211 Ok(())
212 }
213
214 #[benchmark(pov_mode = Measured)]
215 fn export_terminal() -> Result<(), BenchmarkError> {
216 #[cfg(test)]
217 crate::mock::ElectionStart::set(sp_runtime::traits::Bounded::max_value());
218 crate::Pallet::<T>::start().unwrap();
219
220 crate::Pallet::<T>::roll_to_signed_and_submit_full_solution()?;
222
223 ensure!(T::Verifier::queued_score().is_none(), "nothing should be queued");
225 crate::Pallet::<T>::roll_until_matches(|| {
226 matches!(CurrentPhase::<T>::get(), Phase::Unsigned(_))
227 });
228
229 ensure!(T::Verifier::queued_score().is_some(), "something should be queued");
231 ensure!(
232 verifier::QueuedSolution::<T>::valid_iter().count() as u32 == T::Pages::get(),
233 "solution should be full"
234 );
235
236 crate::Pallet::<T>::roll_until_matches(|| CurrentPhase::<T>::get().is_done());
238
239 (1..=T::Pages::get() - 1).rev().for_each(T::DataProvider::fetch_page);
241
242 assert_eq!(CurrentPhase::<T>::get(), Phase::Export(0));
243
244 #[block]
245 {
246 T::DataProvider::fetch_page(0);
247 }
248
249 assert_eq!(CurrentPhase::<T>::get(), Phase::Off);
251
252 Ok(())
253 }
254
255 #[benchmark(pov_mode = Measured)]
256 fn manage() -> Result<(), BenchmarkError> {
257 #[block]
259 {}
260 Ok(())
261 }
262
263 impl_benchmark_test_suite!(
264 Pallet,
265 crate::mock::ExtBuilder::full().build_unchecked(),
266 crate::mock::Runtime
267 );
268}