cumulus_pallet_xcmp_queue/
benchmarking.rs1use crate::{weights_ext::get_average_page_pos, *};
19
20use alloc::vec;
21use codec::DecodeAll;
22use frame_benchmarking::v2::*;
23use frame_support::traits::Hooks;
24use frame_system::RawOrigin;
25use xcm::MAX_INSTRUCTIONS_TO_DECODE;
26
27impl EnqueueXcmpMessagesResult {
28 fn is_ok(&self) -> bool {
29 !self.has_dropped_msgs && !self.has_out_of_weight_msgs
30 }
31}
32
33#[benchmarks]
34mod benchmarks {
35 use super::*;
36
37 #[benchmark]
44 fn set_config_with_u32() {
45 #[extrinsic_call]
46 Pallet::<T>::update_resume_threshold(RawOrigin::Root, 1);
47 }
48
49 #[benchmark]
54 fn enqueue_n_bytes_xcmp_message(n: Linear<0, { MaxXcmpMessageLenOf::<T>::get() }>) {
55 #[cfg(test)]
56 {
57 mock::EnqueuedMessages::set(vec![]);
58 }
59
60 let msg = BoundedVec::try_from(vec![0; n as usize]).unwrap();
61
62 #[cfg(not(test))]
63 let fp_before = T::XcmpQueue::footprint(0.into());
64 #[block]
65 {
66 assert!(Pallet::<T>::enqueue_xcmp_messages(
67 0.into(),
68 &[msg.as_bounded_slice()],
69 true,
70 &mut WeightMeter::new()
71 )
72 .is_ok());
73 }
74 #[cfg(not(test))]
75 {
76 let fp_after = T::XcmpQueue::footprint(0.into());
77 assert_eq!(fp_after.ready_pages, fp_before.ready_pages + 1);
78 }
79 }
80
81 #[benchmark]
86 fn enqueue_n_empty_xcmp_messages(n: Linear<0, 1000>) {
87 #[cfg(test)]
88 {
89 mock::EnqueuedMessages::set(vec![]);
90 <QueueConfig<T>>::set(QueueConfigData {
91 suspend_threshold: 1100,
92 drop_threshold: 1100,
93 resume_threshold: 1100,
94 });
95 }
96
97 let msg = BoundedVec::new();
98 let msgs = vec![msg.as_bounded_slice(); n as usize];
99
100 #[cfg(not(test))]
101 let fp_before = T::XcmpQueue::footprint(0.into());
102 #[block]
103 {
104 assert!(Pallet::<T>::enqueue_xcmp_messages(
105 0.into(),
106 &msgs,
107 true,
108 &mut WeightMeter::new()
109 )
110 .is_ok());
111 }
112 #[cfg(not(test))]
113 {
114 let fp_after = T::XcmpQueue::footprint(0.into());
115 if !msgs.is_empty() {
116 assert_eq!(fp_after.ready_pages, fp_before.ready_pages + 1);
117 }
118 }
119 }
120
121 #[benchmark(pov_mode = Measured)]
124 fn enqueue_empty_xcmp_message_at(
125 n: Linear<0, { crate::MaxXcmpMessageLenOf::<T>::get() - 10 }>,
126 ) {
127 #[cfg(test)]
128 {
129 mock::EnqueuedMessages::set(vec![]);
130 }
131
132 assert!(Pallet::<T>::enqueue_xcmp_messages(
133 0.into(),
134 &[BoundedVec::try_from(vec![0; n as usize]).unwrap().as_bounded_slice()],
135 true,
136 &mut WeightMeter::new()
137 )
138 .is_ok());
139
140 #[cfg(not(test))]
141 let fp_before = T::XcmpQueue::footprint(0.into());
142 #[block]
143 {
144 assert!(Pallet::<T>::enqueue_xcmp_messages(
145 0.into(),
146 &[BoundedVec::new().as_bounded_slice()],
147 true,
148 &mut WeightMeter::new()
149 )
150 .is_ok());
151 }
152 #[cfg(not(test))]
153 {
154 let fp_after = T::XcmpQueue::footprint(0.into());
155 assert_eq!(fp_after.ready_pages, fp_before.ready_pages);
156 }
157 }
158
159 #[benchmark]
163 fn enqueue_n_full_pages(n: Linear<0, 100>) {
164 #[cfg(test)]
165 {
166 mock::EnqueuedMessages::set(vec![]);
167 }
168 <QueueConfig<T>>::set(QueueConfigData {
169 suspend_threshold: 200,
170 drop_threshold: 200,
171 resume_threshold: 200,
172 });
173
174 let max_msg_len = MaxXcmpMessageLenOf::<T>::get() as usize;
175 let mut msgs = vec![];
176 for _i in 0..n {
177 let msg = BoundedVec::try_from(vec![0; max_msg_len]).unwrap();
178 msgs.push(msg);
179 }
180
181 #[cfg(not(test))]
182 let fp_before = T::XcmpQueue::footprint(0.into());
183 #[block]
184 {
185 assert!(Pallet::<T>::enqueue_xcmp_messages(
186 0.into(),
187 &msgs.iter().map(|msg| msg.as_bounded_slice()).collect::<Vec<_>>(),
188 true,
189 &mut WeightMeter::new()
190 )
191 .is_ok());
192 }
193 #[cfg(not(test))]
194 {
195 let fp_after = T::XcmpQueue::footprint(0.into());
196 assert_eq!(fp_after.ready_pages, fp_before.ready_pages + n);
197 }
198 }
199
200 #[benchmark(pov_mode = Measured)]
201 fn enqueue_1000_small_xcmp_messages() {
202 #[cfg(test)]
203 {
204 <QueueConfig<T>>::set(QueueConfigData {
205 suspend_threshold: 1100,
206 drop_threshold: 1100,
207 resume_threshold: 1100,
208 });
209 }
210
211 assert!(Pallet::<T>::enqueue_xcmp_messages(
212 0.into(),
213 &[BoundedVec::try_from(vec![
214 0;
215 get_average_page_pos(MaxXcmpMessageLenOf::<T>::get())
216 as usize
217 ])
218 .unwrap()
219 .as_bounded_slice()],
220 true,
221 &mut WeightMeter::new()
222 )
223 .is_ok());
224
225 let mut msgs = vec![];
226 for _i in 0..1000 {
227 msgs.push(BoundedVec::try_from(vec![0; 3]).unwrap());
228 }
229
230 #[cfg(not(test))]
231 let fp_before = T::XcmpQueue::footprint(0.into());
232 #[block]
233 {
234 assert!(Pallet::<T>::enqueue_xcmp_messages(
235 0.into(),
236 &msgs.iter().map(|msg| msg.as_bounded_slice()).collect::<Vec<_>>(),
237 true,
238 &mut WeightMeter::new()
239 )
240 .is_ok());
241 }
242 #[cfg(not(test))]
243 {
244 let fp_after = T::XcmpQueue::footprint(0.into());
245 assert_eq!(fp_after.ready_pages, fp_before.ready_pages);
246 }
247 }
248
249 #[benchmark]
250 fn suspend_channel() {
251 let para = 123.into();
252 let data = ChannelSignal::Suspend.encode();
253
254 #[block]
255 {
256 ChannelSignal::decode_all(&mut &data[..]).unwrap();
257 Pallet::<T>::suspend_channel(para);
258 }
259
260 assert_eq!(
261 OutboundXcmpStatus::<T>::get()
262 .iter()
263 .find(|p| p.recipient == para)
264 .unwrap()
265 .state,
266 OutboundState::Suspended
267 );
268 }
269
270 #[benchmark]
271 fn resume_channel() {
272 let para = 123.into();
273 let data = ChannelSignal::Resume.encode();
274
275 Pallet::<T>::suspend_channel(para);
276
277 #[block]
278 {
279 ChannelSignal::decode_all(&mut &data[..]).unwrap();
280 Pallet::<T>::resume_channel(para);
281 }
282
283 assert!(
284 OutboundXcmpStatus::<T>::get().iter().all(|p| p.recipient != para),
285 "No messages in the channel; therefore removed."
286 );
287 }
288
289 #[benchmark]
291 fn take_first_concatenated_xcm(
292 n: Linear<0, { MAX_INSTRUCTIONS_TO_DECODE as u32 - MAX_XCM_DECODE_DEPTH }>,
293 ) {
294 let mut xcm = Xcm::<T>(vec![ClearOrigin; n as usize]);
295 for _ in 0..MAX_XCM_DECODE_DEPTH - 1 {
296 xcm = Xcm::<T>(vec![Instruction::SetAppendix(xcm)]);
297 }
298 let data = VersionedXcm::<T>::from(xcm).encode();
299
300 #[block]
301 {
302 Pallet::<T>::take_first_concatenated_xcm(&mut &data[..], &mut WeightMeter::new())
303 .unwrap();
304 }
305 }
306
307 #[benchmark]
309 fn on_idle_good_msg() {
310 use migration::v3;
311
312 let block = 5;
313 let para = ParaId::from(4);
314 let message = vec![123u8; MaxXcmpMessageLenOf::<T>::get() as usize];
315 let message_metadata = vec![(block, XcmpMessageFormat::ConcatenatedVersionedXcm)];
316
317 v3::InboundXcmpMessages::<T>::insert(para, block, message);
318 v3::InboundXcmpStatus::<T>::set(Some(vec![v3::InboundChannelDetails {
319 sender: para,
320 state: v3::InboundState::Ok,
321 message_metadata,
322 }]));
323
324 #[block]
325 {
326 Pallet::<T>::on_idle(0u32.into(), Weight::MAX);
327 }
328 }
329
330 #[benchmark]
332 fn on_idle_large_msg() {
333 use migration::v3;
334
335 let block = 5;
336 let para = ParaId::from(4);
337 let message = vec![123u8; 1 << 16]; let message_metadata = vec![(block, XcmpMessageFormat::ConcatenatedVersionedXcm)];
339
340 v3::InboundXcmpMessages::<T>::insert(para, block, message);
341 v3::InboundXcmpStatus::<T>::set(Some(vec![v3::InboundChannelDetails {
342 sender: para,
343 state: v3::InboundState::Ok,
344 message_metadata,
345 }]));
346
347 #[block]
348 {
349 Pallet::<T>::on_idle(0u32.into(), Weight::MAX);
350 }
351 }
352
353 impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
354}