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