@@ -39,7 +39,7 @@ use self::{
39
39
use frame_benchmarking:: { benchmarks, account, whitelisted_caller} ;
40
40
use frame_system:: { Module as System , RawOrigin } ;
41
41
use parity_wasm:: elements:: { Instruction , ValueType , BlockType } ;
42
- use sp_runtime:: traits:: { Hash , Bounded } ;
42
+ use sp_runtime:: traits:: { Hash , Bounded , Zero } ;
43
43
use sp_std:: { default:: Default , convert:: { TryInto } , vec:: Vec , vec} ;
44
44
use pallet_contracts_primitives:: RentProjection ;
45
45
@@ -209,37 +209,52 @@ where
209
209
}
210
210
}
211
211
212
- /// A `Contract` that was evicted after accumulating some storage.
212
+ /// A `Contract` that contains some storage items .
213
213
///
214
- /// This is used to benchmark contract resurrection.
215
- struct Tombstone < T : Config > {
214
+ /// This is used to benchmark contract destruction and resurection. Those operations'
215
+ /// weight depend on the amount of storage accumulated.
216
+ struct ContractWithStorage < T : Config > {
216
217
/// The contract that was evicted.
217
218
contract : Contract < T > ,
218
219
/// The storage the contract held when it was avicted.
219
220
storage : Vec < ( StorageKey , Vec < u8 > ) > ,
220
221
}
221
222
222
- impl < T : Config > Tombstone < T >
223
+ impl < T : Config > ContractWithStorage < T >
223
224
where
224
225
T : Config ,
225
226
T :: AccountId : UncheckedFrom < T :: Hash > + AsRef < [ u8 ] > ,
226
227
{
227
- /// Create and evict a new contract with the supplied storage item count and size each .
228
+ /// Same as [`Self::with_code`] but with dummy contract code .
228
229
fn new ( stor_num : u32 , stor_size : u32 ) -> Result < Self , & ' static str > {
229
- let contract = Contract :: < T > :: new ( WasmModule :: dummy ( ) , vec ! [ ] , Endow :: CollectRent ) ?;
230
+ Self :: with_code ( WasmModule :: dummy ( ) , stor_num, stor_size)
231
+ }
232
+
233
+ /// Create and evict a new contract with the supplied storage item count and size each.
234
+ fn with_code ( code : WasmModule < T > , stor_num : u32 , stor_size : u32 ) -> Result < Self , & ' static str > {
235
+ let contract = Contract :: < T > :: new ( code, vec ! [ ] , Endow :: CollectRent ) ?;
230
236
let storage_items = create_storage :: < T > ( stor_num, stor_size) ?;
231
237
contract. store ( & storage_items) ?;
232
- System :: < T > :: set_block_number (
233
- contract. eviction_at ( ) ? + T :: SignedClaimHandicap :: get ( ) + 5u32 . into ( )
234
- ) ;
235
- Rent :: < T > :: collect ( & contract. account_id ) ;
236
- contract. ensure_tombstone ( ) ?;
237
-
238
- Ok ( Tombstone {
238
+ Ok ( Self {
239
239
contract,
240
240
storage : storage_items,
241
241
} )
242
242
}
243
+
244
+ /// Increase the system block number so that this contract is eligible for eviction.
245
+ fn set_block_num_for_eviction ( & self ) -> Result < ( ) , & ' static str > {
246
+ System :: < T > :: set_block_number (
247
+ self . contract . eviction_at ( ) ? + T :: SignedClaimHandicap :: get ( ) + 5u32 . into ( )
248
+ ) ;
249
+ Ok ( ( ) )
250
+ }
251
+
252
+ /// Evict this contract.
253
+ fn evict ( & mut self ) -> Result < ( ) , & ' static str > {
254
+ self . set_block_num_for_eviction ( ) ?;
255
+ Rent :: < T > :: snitch_contract_should_be_evicted ( & self . contract . account_id , Zero :: zero ( ) ) ?;
256
+ self . contract . ensure_tombstone ( )
257
+ }
243
258
}
244
259
245
260
/// Generate `stor_num` storage items. Each has the size `stor_size`.
@@ -270,6 +285,30 @@ benchmarks! {
270
285
_ {
271
286
}
272
287
288
+ // The base weight without any actual work performed apart from the setup costs.
289
+ on_initialize { } : {
290
+ Storage :: <T >:: process_deletion_queue_batch( Weight :: max_value( ) )
291
+ }
292
+
293
+ on_initialize_per_trie_key {
294
+ let k in 0 ..1024 ;
295
+ let instance = ContractWithStorage :: <T >:: new( k, T :: MaxValueSize :: get( ) ) ?;
296
+ Storage :: <T >:: queue_trie_for_deletion( & instance. contract. alive_info( ) ?) ?;
297
+ } : {
298
+ Storage :: <T >:: process_deletion_queue_batch( Weight :: max_value( ) )
299
+ }
300
+
301
+ on_initialize_per_queue_item {
302
+ let q in 0 ..1024 . min( T :: DeletionQueueDepth :: get( ) ) ;
303
+ for i in 0 .. q {
304
+ let instance = Contract :: <T >:: with_index( i, WasmModule :: dummy( ) , vec![ ] , Endow :: Max ) ?;
305
+ Storage :: <T >:: queue_trie_for_deletion( & instance. alive_info( ) ?) ?;
306
+ ContractInfoOf :: <T >:: remove( instance. account_id) ;
307
+ }
308
+ } : {
309
+ Storage :: <T >:: process_deletion_queue_batch( Weight :: max_value( ) )
310
+ }
311
+
273
312
// This extrinsic is pretty much constant as it is only a simple setter.
274
313
update_schedule {
275
314
let schedule = Schedule {
@@ -650,7 +689,8 @@ benchmarks! {
650
689
// Restore just moves the trie id from origin to destination and therefore
651
690
// does not depend on the size of the destination contract. However, to not
652
691
// trigger any edge case we won't use an empty contract as destination.
653
- let tombstone = Tombstone :: <T >:: new( 10 , T :: MaxValueSize :: get( ) ) ?;
692
+ let mut tombstone = ContractWithStorage :: <T >:: new( 10 , T :: MaxValueSize :: get( ) ) ?;
693
+ tombstone. evict( ) ?;
654
694
655
695
let dest = tombstone. contract. account_id. encode( ) ;
656
696
let dest_len = dest. len( ) ;
@@ -723,7 +763,8 @@ benchmarks! {
723
763
724
764
seal_restore_to_per_delta {
725
765
let d in 0 .. API_BENCHMARK_BATCHES ;
726
- let tombstone = Tombstone :: <T >:: new( 0 , 0 ) ?;
766
+ let mut tombstone = ContractWithStorage :: <T >:: new( 0 , 0 ) ?;
767
+ tombstone. evict( ) ?;
727
768
let delta = create_storage:: <T >( d * API_BENCHMARK_BATCH_SIZE , T :: MaxValueSize :: get( ) ) ?;
728
769
729
770
let dest = tombstone. contract. account_id. encode( ) ;
@@ -2368,7 +2409,20 @@ benchmarks! {
2368
2409
#[ extra]
2369
2410
print_schedule {
2370
2411
#[ cfg( feature = "std" ) ]
2371
- println!( "{:#?}" , Schedule :: <T >:: default ( ) ) ;
2412
+ {
2413
+ let weight_per_key = T :: WeightInfo :: on_initialize_per_trie_key( 1 ) -
2414
+ T :: WeightInfo :: on_initialize_per_trie_key( 0 ) ;
2415
+ let weight_per_queue_item = T :: WeightInfo :: on_initialize_per_queue_item( 1 ) -
2416
+ T :: WeightInfo :: on_initialize_per_queue_item( 0 ) ;
2417
+ let weight_limit = T :: DeletionWeightLimit :: get( ) ;
2418
+ let queue_depth: u64 = T :: DeletionQueueDepth :: get( ) . into( ) ;
2419
+ println!( "{:#?}" , Schedule :: <T >:: default ( ) ) ;
2420
+ println!( "###############################################" ) ;
2421
+ println!( "Lazy deletion throughput per block (empty queue, full queue): {}, {}" ,
2422
+ weight_limit / weight_per_key,
2423
+ ( weight_limit - weight_per_queue_item * queue_depth) / weight_per_key,
2424
+ ) ;
2425
+ }
2372
2426
#[ cfg( not( feature = "std" ) ) ]
2373
2427
return Err ( "Run this bench with a native runtime in order to see the schedule." ) ;
2374
2428
} : { }
@@ -2394,6 +2448,10 @@ mod tests {
2394
2448
}
2395
2449
}
2396
2450
2451
+ create_test ! ( on_initialize) ;
2452
+ create_test ! ( on_initialize_per_trie_key) ;
2453
+ create_test ! ( on_initialize_per_queue_item) ;
2454
+
2397
2455
create_test ! ( update_schedule) ;
2398
2456
create_test ! ( put_code) ;
2399
2457
create_test ! ( instantiate) ;
0 commit comments