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