Skip to content

Commit a0c7373

Browse files
authored
Merge pull request #240 from rmrk-team/bechmark_nested_calls
Benchmark burn_nft call with deep nesting
2 parents 6c695c3 + df42df9 commit a0c7373

File tree

6 files changed

+85
-53
lines changed

6 files changed

+85
-53
lines changed

pallets/rmrk-core/src/benchmarking.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,17 @@ fn mint_test_nft<T: Config>(
101101
nft_id
102102
}
103103

104+
// premint nfts & make deep nested chain of nfts ( send child to parent )
105+
fn mint_and_send_to_parent<T: Config>(owner: T::AccountId, collection_id: T::CollectionId, n: u32) {
106+
for i in 1..n {
107+
let id = mint_test_nft::<T>(owner.clone(), None, collection_id, i);
108+
let parent_nft_id = T::Helper::item(i.saturating_sub(1));
109+
let new_owner =
110+
AccountIdOrCollectionNftTuple::CollectionAndNftTuple(collection_id, parent_nft_id);
111+
send_test_nft::<T>(owner.clone(), collection_id, id, new_owner);
112+
}
113+
}
114+
104115
// Send nft to Account or to another nft
105116
fn send_test_nft<T: Config>(
106117
owner: T::AccountId,
@@ -241,8 +252,10 @@ benchmarks! {
241252
let owner: T::AccountId = whitelisted_caller();
242253
let collection_index = 1;
243254
let collection_id = create_test_collection::<T>(owner.clone(), collection_index);
244-
let nft_id = mint_test_nft::<T>(owner.clone(), None, collection_id, 42);
255+
let nft_id = mint_test_nft::<T>(owner.clone(), None, collection_id, 0);
245256

257+
let n in 1 .. T::NestingBudget::get();
258+
mint_and_send_to_parent::<T>(owner.clone(), collection_id, n);
246259
}: _(RawOrigin::Signed(owner.clone()), collection_id, nft_id)
247260
verify {
248261
assert_last_event::<T>(Event::NFTBurned { owner, collection_id, nft_id }.into());
@@ -274,16 +287,20 @@ benchmarks! {
274287
}
275288

276289
reject_nft {
290+
let n in 1 .. T::NestingBudget::get();
277291
let alice: T::AccountId = whitelisted_caller();
278-
let collection_index = 1;
279-
let collection_id = create_test_collection::<T>(alice.clone(), collection_index);
280-
let nft_id1 = mint_test_nft::<T>(alice.clone(), None, collection_id, 1);
281-
let child_nft = mint_test_nft::<T>(alice.clone(), None, collection_id, 2);
292+
let collection_index = 1;
293+
let collection_id = create_test_collection::<T>(alice.clone(), collection_index);
294+
let nft_id1 = mint_test_nft::<T>(alice.clone(), None, collection_id, 0);
295+
let child_nft = mint_test_nft::<T>(alice.clone(), None, collection_id, 42);
282296
// Alice sends NFT (0,1) to Bob's account
283297
let bob = funded_account::<T>("bob", 0);
284298
let new_owner = AccountIdOrCollectionNftTuple::AccountId(bob.clone());
285299
send_test_nft::<T>(alice.clone(), collection_id, nft_id1, new_owner.clone());
286300

301+
302+
mint_and_send_to_parent::<T>(alice.clone(), collection_id, n);
303+
287304
// Alice sends child NFT (0,2) to parent NFT (0,1)
288305
let parent_nft = AccountIdOrCollectionNftTuple::CollectionAndNftTuple(collection_id, nft_id1);
289306
send_test_nft::<T>(alice.clone(), collection_id, child_nft, parent_nft.clone());

pallets/rmrk-core/src/functions.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ impl<T: Config>
551551
collection_id: T::CollectionId,
552552
nft_id: T::ItemId,
553553
budget: &dyn Budget,
554-
) -> sp_std::result::Result<(T::CollectionId, T::ItemId), DispatchError> {
554+
) -> DispatchResultWithPostInfo {
555555
// Remove self from parent's Children storage
556556
if let Some(nft) = Self::nfts(collection_id, nft_id) {
557557
if let AccountIdOrCollectionNftTuple::CollectionAndNftTuple(parent_col, parent_nft) =
@@ -588,7 +588,10 @@ impl<T: Config>
588588

589589
Self::deposit_event(Event::NFTBurned { owner, nft_id, collection_id });
590590

591-
Ok((collection_id, nft_id))
591+
Ok(Some(<T as pallet::Config>::WeightInfo::burn_nft(
592+
T::NestingBudget::get() - budget.val(),
593+
))
594+
.into())
592595
}
593596

594597
fn nft_send(
@@ -736,7 +739,7 @@ impl<T: Config>
736739
sender: T::AccountId,
737740
collection_id: T::CollectionId,
738741
nft_id: T::ItemId,
739-
) -> Result<(T::AccountId, T::CollectionId, T::ItemId), DispatchError> {
742+
) -> DispatchResultWithPostInfo {
740743
// Look up root owner in Uniques to ensure permissions
741744
let budget = budget::Value::new(T::NestingBudget::get());
742745
let (root_owner, _root_nft) =
@@ -768,9 +771,11 @@ impl<T: Config>
768771
let _rejecting_nft =
769772
Nfts::<T>::get(collection_id, nft_id).ok_or(Error::<T>::NoAvailableNftId)?;
770773

771-
Self::nft_burn(sender.clone(), collection_id, nft_id, &budget)?;
774+
let result = Self::nft_burn(sender.clone(), collection_id, nft_id, &budget);
775+
776+
Self::deposit_event(Event::NFTRejected { sender: sender.clone(), collection_id, nft_id });
772777

773-
Ok((sender, collection_id, nft_id))
778+
result
774779
}
775780
}
776781

pallets/rmrk-core/src/lib.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -535,22 +535,19 @@ pub mod pallet {
535535
}
536536

537537
/// burn nft
538-
#[pallet::weight(<T as pallet::Config>::WeightInfo::burn_nft())]
538+
#[pallet::weight(<T as pallet::Config>::WeightInfo::burn_nft(T::NestingBudget::get()))]
539539
#[transactional]
540540
pub fn burn_nft(
541541
origin: OriginFor<T>,
542542
collection_id: T::CollectionId,
543543
nft_id: T::ItemId,
544-
) -> DispatchResult {
544+
) -> DispatchResultWithPostInfo {
545545
let sender = ensure_signed(origin)?;
546546
let budget = budget::Value::new(T::NestingBudget::get());
547547
let (root_owner, _) = Pallet::<T>::lookup_root_owner(collection_id, nft_id, &budget)?;
548548
// Check ownership
549549
ensure!(sender == root_owner, Error::<T>::NoPermission);
550-
let (_collection_id, _nft_id) =
551-
Self::nft_burn(root_owner, collection_id, nft_id, &budget)?;
552-
553-
Ok(())
550+
Self::nft_burn(root_owner, collection_id, nft_id, &budget)
554551
}
555552

556553
/// destroy collection
@@ -639,19 +636,16 @@ pub mod pallet {
639636
/// - `origin`: sender of the transaction
640637
/// - `collection_id`: collection id of the nft to be accepted
641638
/// - `nft_id`: nft id of the nft to be accepted
642-
#[pallet::weight(<T as pallet::Config>::WeightInfo::reject_nft())]
639+
#[pallet::weight(<T as pallet::Config>::WeightInfo::reject_nft(T::NestingBudget::get()))]
643640
#[transactional]
644641
pub fn reject_nft(
645642
origin: OriginFor<T>,
646643
collection_id: T::CollectionId,
647644
nft_id: T::ItemId,
648-
) -> DispatchResult {
645+
) -> DispatchResultWithPostInfo {
649646
let sender = ensure_signed(origin)?;
650647

651-
let (sender, collection_id, nft_id) = Self::nft_reject(sender, collection_id, nft_id)?;
652-
653-
Self::deposit_event(Event::NFTRejected { sender, collection_id, nft_id });
654-
Ok(())
648+
Self::nft_reject(sender, collection_id, nft_id)
655649
}
656650

657651
/// Change the issuer of a collection

pallets/rmrk-core/src/weights.rs

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
//! Autogenerated weights for `pallet_rmrk_core`
33
//!
44
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
5-
//! DATE: 2022-11-11, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
6-
//! HOSTNAME: `ilias-MacBook-Pro.local`, CPU: `<UNKNOWN>`
5+
//! DATE: 2022-11-10, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
6+
//! HOSTNAME: `ilias-MBP.localdomain`, CPU: `<UNKNOWN>`
77
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
88
99
// Executed Command:
@@ -39,9 +39,9 @@ pub trait WeightInfo {
3939
fn destroy_collection() -> Weight;
4040
fn send_to_account() -> Weight;
4141
fn send_to_nft() -> Weight;
42-
fn burn_nft() -> Weight;
42+
fn burn_nft(n: u32) -> Weight;
4343
fn accept_nft() -> Weight;
44-
fn reject_nft() -> Weight;
44+
fn reject_nft(n: u32) -> Weight;
4545
fn change_collection_issuer() -> Weight;
4646
fn set_property() -> Weight;
4747
fn lock_collection() -> Weight;
@@ -55,14 +55,13 @@ pub trait WeightInfo {
5555
fn replace_resource() -> Weight;
5656
}
5757

58-
/// Weight functions for `pallet_rmrk_core`.
5958
pub struct SubstrateWeight<T>(PhantomData<T>);
6059
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
6160
// Storage: Uniques Class (r:1 w:1)
6261
// Storage: RmrkCore Collections (r:0 w:1)
6362
// Storage: Uniques ClassAccount (r:0 w:1)
6463
fn create_collection() -> Weight {
65-
Weight::from_ref_time(36_000_000 as u64)
64+
Weight::from_ref_time(38_000_000 as u64)
6665
.saturating_add(T::DbWeight::get().reads(1 as u64))
6766
.saturating_add(T::DbWeight::get().writes(3 as u64))
6867
}
@@ -73,7 +72,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
7372
// Storage: Uniques CollectionMaxSupply (r:1 w:0)
7473
// Storage: Uniques Account (r:0 w:1)
7574
fn mint_nft() -> Weight {
76-
Weight::from_ref_time(54_000_000 as u64)
75+
Weight::from_ref_time(55_000_000 as u64)
7776
.saturating_add(T::DbWeight::get().reads(5 as u64))
7877
.saturating_add(T::DbWeight::get().writes(5 as u64))
7978
}
@@ -85,7 +84,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
8584
// Storage: RmrkCore Children (r:0 w:1)
8685
// Storage: Uniques Account (r:0 w:1)
8786
fn mint_nft_directly_to_nft() -> Weight {
88-
Weight::from_ref_time(59_000_000 as u64)
87+
Weight::from_ref_time(60_000_000 as u64)
8988
.saturating_add(T::DbWeight::get().reads(6 as u64))
9089
.saturating_add(T::DbWeight::get().writes(6 as u64))
9190
}
@@ -96,7 +95,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
9695
// Storage: Uniques ClassMetadataOf (r:0 w:1)
9796
// Storage: Uniques CollectionMaxSupply (r:0 w:1)
9897
fn destroy_collection() -> Weight {
99-
Weight::from_ref_time(60_000_000 as u64)
98+
Weight::from_ref_time(61_000_000 as u64)
10099
.saturating_add(T::DbWeight::get().reads(3 as u64))
101100
.saturating_add(T::DbWeight::get().writes(5 as u64))
102101
}
@@ -107,7 +106,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
107106
// Storage: Uniques Account (r:0 w:2)
108107
// Storage: Uniques ItemPriceOf (r:0 w:1)
109108
fn send_to_account() -> Weight {
110-
Weight::from_ref_time(48_000_000 as u64)
109+
Weight::from_ref_time(50_000_000 as u64)
111110
.saturating_add(T::DbWeight::get().reads(4 as u64))
112111
.saturating_add(T::DbWeight::get().writes(5 as u64))
113112
}
@@ -119,7 +118,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
119118
// Storage: Uniques Account (r:0 w:2)
120119
// Storage: Uniques ItemPriceOf (r:0 w:1)
121120
fn send_to_nft() -> Weight {
122-
Weight::from_ref_time(56_000_000 as u64)
121+
Weight::from_ref_time(58_000_000 as u64)
123122
.saturating_add(T::DbWeight::get().reads(6 as u64))
124123
.saturating_add(T::DbWeight::get().writes(6 as u64))
125124
}
@@ -130,15 +129,20 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
130129
// Storage: Uniques Class (r:1 w:1)
131130
// Storage: Uniques Account (r:0 w:1)
132131
// Storage: Uniques ItemPriceOf (r:0 w:1)
133-
fn burn_nft() -> Weight {
134-
Weight::from_ref_time(63_000_000 as u64)
135-
.saturating_add(T::DbWeight::get().reads(5 as u64))
136-
.saturating_add(T::DbWeight::get().writes(6 as u64))
132+
/// The range of component `n` is `[1, 20]`.
133+
fn burn_nft(n: u32, ) -> Weight {
134+
Weight::from_ref_time(0 as u64)
135+
// Standard Error: 400_000
136+
.saturating_add(Weight::from_ref_time(79_057_000 as u64).saturating_mul(n as u64))
137+
.saturating_add(T::DbWeight::get().reads(1 as u64))
138+
.saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(n as u64)))
139+
.saturating_add(T::DbWeight::get().writes(1 as u64))
140+
.saturating_add(T::DbWeight::get().writes((5 as u64).saturating_mul(n as u64)))
137141
}
138142
// Storage: Uniques Asset (r:2 w:0)
139143
// Storage: RmrkCore Nfts (r:1 w:1)
140144
fn accept_nft() -> Weight {
141-
Weight::from_ref_time(33_000_000 as u64)
145+
Weight::from_ref_time(35_000_000 as u64)
142146
.saturating_add(T::DbWeight::get().reads(3 as u64))
143147
.saturating_add(T::DbWeight::get().writes(1 as u64))
144148
}
@@ -149,9 +153,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
149153
// Storage: Uniques Class (r:1 w:1)
150154
// Storage: Uniques Account (r:0 w:1)
151155
// Storage: Uniques ItemPriceOf (r:0 w:1)
152-
fn reject_nft() -> Weight {
153-
Weight::from_ref_time(82_000_000 as u64)
154-
.saturating_add(T::DbWeight::get().reads(7 as u64))
156+
/// The range of component `n` is `[1, 20]`.
157+
fn reject_nft(n: u32, ) -> Weight {
158+
Weight::from_ref_time(82_707_000 as u64)
159+
// Standard Error: 10_000
160+
.saturating_add(Weight::from_ref_time(128_000 as u64).saturating_mul(n as u64))
161+
.saturating_add(T::DbWeight::get().reads(6 as u64))
155162
.saturating_add(T::DbWeight::get().writes(7 as u64))
156163
}
157164
// Storage: RmrkCore Collections (r:1 w:1)
@@ -160,7 +167,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
160167
// Storage: System Account (r:1 w:1)
161168
// Storage: Uniques ClassAccount (r:0 w:2)
162169
fn change_collection_issuer() -> Weight {
163-
Weight::from_ref_time(57_000_000 as u64)
170+
Weight::from_ref_time(56_000_000 as u64)
164171
.saturating_add(T::DbWeight::get().reads(4 as u64))
165172
.saturating_add(T::DbWeight::get().writes(6 as u64))
166173
}
@@ -169,13 +176,13 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
169176
// Storage: Uniques Asset (r:1 w:0)
170177
// Storage: RmrkCore Properties (r:0 w:1)
171178
fn set_property() -> Weight {
172-
Weight::from_ref_time(30_000_000 as u64)
179+
Weight::from_ref_time(29_000_000 as u64)
173180
.saturating_add(T::DbWeight::get().reads(3 as u64))
174181
.saturating_add(T::DbWeight::get().writes(1 as u64))
175182
}
176183
// Storage: RmrkCore Collections (r:1 w:1)
177184
fn lock_collection() -> Weight {
178-
Weight::from_ref_time(23_000_000 as u64)
185+
Weight::from_ref_time(22_000_000 as u64)
179186
.saturating_add(T::DbWeight::get().reads(1 as u64))
180187
.saturating_add(T::DbWeight::get().writes(1 as u64))
181188
}
@@ -184,13 +191,13 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
184191
Weight::from_ref_time(25_000_000 as u64)
185192
.saturating_add(T::DbWeight::get().reads(1 as u64))
186193
.saturating_add(T::DbWeight::get().writes(1 as u64))
187-
}
194+
}
188195
// Storage: RmrkCore Collections (r:1 w:0)
189196
// Storage: Uniques Asset (r:1 w:0)
190197
// Storage: RmrkCore Lock (r:1 w:0)
191198
// Storage: RmrkCore Resources (r:1 w:1)
192199
fn add_basic_resource() -> Weight {
193-
Weight::from_ref_time(32_000_000 as u64)
200+
Weight::from_ref_time(31_000_000 as u64)
194201
.saturating_add(T::DbWeight::get().reads(4 as u64))
195202
.saturating_add(T::DbWeight::get().writes(1 as u64))
196203
}
@@ -200,7 +207,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
200207
// Storage: RmrkCore Resources (r:1 w:1)
201208
// Storage: RmrkCore EquippableBases (r:0 w:1)
202209
fn add_composable_resource() -> Weight {
203-
Weight::from_ref_time(34_000_000 as u64)
210+
Weight::from_ref_time(33_000_000 as u64)
204211
.saturating_add(T::DbWeight::get().reads(4 as u64))
205212
.saturating_add(T::DbWeight::get().writes(2 as u64))
206213
}
@@ -242,10 +249,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
242249
// Storage: RmrkCore Priorities (r:0 w:1)
243250
/// The range of component `n` is `[1, 25]`.
244251
fn set_priority(n: u32, ) -> Weight {
245-
Weight::from_ref_time(22_537_000 as u64)
246-
// Standard Error: 7_000
247-
.saturating_add(Weight::from_ref_time(2_385_000 as u64).saturating_mul(n as u64))
252+
Weight::from_ref_time(21_901_000 as u64)
253+
// Standard Error: 3_000
254+
.saturating_add(Weight::from_ref_time(2_436_000 as u64).saturating_mul(n as u64))
248255
.saturating_add(T::DbWeight::get().reads(2 as u64))
249256
.saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(n as u64)))
250257
}
251-
}
258+
}

traits/src/budget.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ pub trait Budget {
88
/// Returns true while not exceeded
99
/// Implementations should use interior mutabilitiy
1010
fn consume_custom(&self, calls: u32) -> bool;
11+
12+
fn val(&self) -> u32 {
13+
self.get_value()
14+
}
15+
16+
fn get_value(&self) -> u32;
1117
}
1218

1319
pub struct Value(Cell<u32>);
@@ -29,4 +35,7 @@ impl Budget for Value {
2935
self.0.set(result);
3036
true
3137
}
38+
fn get_value(&self) -> u32 {
39+
self.0.get()
40+
}
3241
}

traits/src/nft.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub trait Nft<AccountId, BoundedString, BoundedResourceVec, CollectionId, NftId>
106106
collection_id: CollectionId,
107107
nft_id: NftId,
108108
budget: &dyn Budget,
109-
) -> Result<(CollectionId, NftId), DispatchError>;
109+
) -> DispatchResultWithPostInfo;
110110
fn nft_send(
111111
sender: AccountId,
112112
collection_id: CollectionId,
@@ -123,5 +123,5 @@ pub trait Nft<AccountId, BoundedString, BoundedResourceVec, CollectionId, NftId>
123123
sender: AccountId,
124124
collection_id: CollectionId,
125125
nft_id: NftId,
126-
) -> Result<(AccountId, CollectionId, NftId), DispatchError>;
126+
) -> DispatchResultWithPostInfo;
127127
}

0 commit comments

Comments
 (0)