@@ -30,7 +30,8 @@ const MEMORY_CACHE_SIZE: Size = Size::mebi(200);
30
30
const INSTANTIATION_THREADS : usize = 128 ;
31
31
const CONTRACTS : u64 = 10 ;
32
32
33
- static CONTRACT : & [ u8 ] = include_bytes ! ( "../testdata/hackatom.wasm" ) ;
33
+ const DEFAULT_CAPABILITIES : & str = "cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,iterator,staking" ;
34
+ static HACKATOM : & [ u8 ] = include_bytes ! ( "../testdata/hackatom.wasm" ) ;
34
35
static CYBERPUNK : & [ u8 ] = include_bytes ! ( "../testdata/cyberpunk.wasm" ) ;
35
36
36
37
fn bench_instance ( c : & mut Criterion ) {
@@ -41,7 +42,7 @@ fn bench_instance(c: &mut Criterion) {
41
42
let backend = mock_backend ( & [ ] ) ;
42
43
let ( instance_options, memory_limit) = mock_instance_options ( ) ;
43
44
let _instance =
44
- Instance :: from_code ( CONTRACT , backend, instance_options, memory_limit) . unwrap ( ) ;
45
+ Instance :: from_code ( HACKATOM , backend, instance_options, memory_limit) . unwrap ( ) ;
45
46
} ) ;
46
47
} ) ;
47
48
@@ -51,7 +52,7 @@ fn bench_instance(c: &mut Criterion) {
51
52
gas_limit : HIGH_GAS_LIMIT ,
52
53
} ;
53
54
let mut instance =
54
- Instance :: from_code ( CONTRACT , backend, much_gas, Some ( DEFAULT_MEMORY_LIMIT ) ) . unwrap ( ) ;
55
+ Instance :: from_code ( HACKATOM , backend, much_gas, Some ( DEFAULT_MEMORY_LIMIT ) ) . unwrap ( ) ;
55
56
56
57
b. iter ( || {
57
58
let info = mock_info ( & instance. api ( ) . addr_make ( "creator" ) , & coins ( 1000 , "earth" ) ) ;
@@ -75,7 +76,7 @@ fn bench_instance(c: &mut Criterion) {
75
76
gas_limit : HIGH_GAS_LIMIT ,
76
77
} ;
77
78
let mut instance =
78
- Instance :: from_code ( CONTRACT , backend, much_gas, Some ( DEFAULT_MEMORY_LIMIT ) ) . unwrap ( ) ;
79
+ Instance :: from_code ( HACKATOM , backend, much_gas, Some ( DEFAULT_MEMORY_LIMIT ) ) . unwrap ( ) ;
79
80
80
81
let info = mock_info ( & instance. api ( ) . addr_make ( "creator" ) , & coins ( 1000 , "earth" ) ) ;
81
82
let verifier = instance. api ( ) . addr_make ( "verifies" ) ;
@@ -129,7 +130,7 @@ fn bench_cache(c: &mut Criterion) {
129
130
130
131
let options = CacheOptions :: new (
131
132
TempDir :: new ( ) . unwrap ( ) . into_path ( ) ,
132
- capabilities_from_csv ( "iterator,staking" ) ,
133
+ capabilities_from_csv ( DEFAULT_CAPABILITIES ) ,
133
134
MEMORY_CACHE_SIZE ,
134
135
DEFAULT_MEMORY_LIMIT ,
135
136
) ;
@@ -139,15 +140,15 @@ fn bench_cache(c: &mut Criterion) {
139
140
unsafe { Cache :: new ( options. clone ( ) ) . unwrap ( ) } ;
140
141
141
142
b. iter ( || {
142
- let result = cache. save_wasm ( CONTRACT ) ;
143
+ let result = cache. save_wasm ( HACKATOM ) ;
143
144
assert ! ( result. is_ok( ) ) ;
144
145
} ) ;
145
146
} ) ;
146
147
147
148
group. bench_function ( "load wasm" , |b| {
148
149
let cache: Cache < MockApi , MockStorage , MockQuerier > =
149
150
unsafe { Cache :: new ( options. clone ( ) ) . unwrap ( ) } ;
150
- let checksum = cache. save_wasm ( CONTRACT ) . unwrap ( ) ;
151
+ let checksum = cache. save_wasm ( HACKATOM ) . unwrap ( ) ;
151
152
152
153
b. iter ( || {
153
154
let result = cache. load_wasm ( & checksum) ;
@@ -160,7 +161,7 @@ fn bench_cache(c: &mut Criterion) {
160
161
let mut cache: Cache < MockApi , MockStorage , MockQuerier > =
161
162
unsafe { Cache :: new ( options) . unwrap ( ) } ;
162
163
cache. set_module_unchecked ( true ) ;
163
- let checksum = cache. save_wasm ( CONTRACT ) . unwrap ( ) ;
164
+ let checksum = cache. save_wasm ( HACKATOM ) . unwrap ( ) ;
164
165
165
166
b. iter ( || {
166
167
let result = cache. load_wasm ( & checksum) ;
@@ -171,7 +172,7 @@ fn bench_cache(c: &mut Criterion) {
171
172
group. bench_function ( "analyze" , |b| {
172
173
let cache: Cache < MockApi , MockStorage , MockQuerier > =
173
174
unsafe { Cache :: new ( options. clone ( ) ) . unwrap ( ) } ;
174
- let checksum = cache. save_wasm ( CONTRACT ) . unwrap ( ) ;
175
+ let checksum = cache. save_wasm ( HACKATOM ) . unwrap ( ) ;
175
176
176
177
b. iter ( || {
177
178
let result = cache. analyze ( & checksum) ;
@@ -182,13 +183,13 @@ fn bench_cache(c: &mut Criterion) {
182
183
group. bench_function ( "instantiate from fs" , |b| {
183
184
let non_memcache = CacheOptions :: new (
184
185
TempDir :: new ( ) . unwrap ( ) . into_path ( ) ,
185
- capabilities_from_csv ( "iterator,staking" ) ,
186
+ capabilities_from_csv ( DEFAULT_CAPABILITIES ) ,
186
187
Size :: new ( 0 ) ,
187
188
DEFAULT_MEMORY_LIMIT ,
188
189
) ;
189
190
let cache: Cache < MockApi , MockStorage , MockQuerier > =
190
191
unsafe { Cache :: new ( non_memcache) . unwrap ( ) } ;
191
- let checksum = cache. save_wasm ( CONTRACT ) . unwrap ( ) ;
192
+ let checksum = cache. save_wasm ( HACKATOM ) . unwrap ( ) ;
192
193
193
194
b. iter ( || {
194
195
let _ = cache
@@ -204,14 +205,14 @@ fn bench_cache(c: &mut Criterion) {
204
205
group. bench_function ( "instantiate from fs unchecked" , |b| {
205
206
let non_memcache = CacheOptions :: new (
206
207
TempDir :: new ( ) . unwrap ( ) . into_path ( ) ,
207
- capabilities_from_csv ( "iterator,staking" ) ,
208
+ capabilities_from_csv ( DEFAULT_CAPABILITIES ) ,
208
209
Size :: new ( 0 ) ,
209
210
DEFAULT_MEMORY_LIMIT ,
210
211
) ;
211
212
let mut cache: Cache < MockApi , MockStorage , MockQuerier > =
212
213
unsafe { Cache :: new ( non_memcache) . unwrap ( ) } ;
213
214
cache. set_module_unchecked ( true ) ;
214
- let checksum = cache. save_wasm ( CONTRACT ) . unwrap ( ) ;
215
+ let checksum = cache. save_wasm ( HACKATOM ) . unwrap ( ) ;
215
216
216
217
b. iter ( || {
217
218
let _ = cache
@@ -225,7 +226,7 @@ fn bench_cache(c: &mut Criterion) {
225
226
} ) ;
226
227
227
228
group. bench_function ( "instantiate from memory" , |b| {
228
- let checksum = Checksum :: generate ( CONTRACT ) ;
229
+ let checksum = Checksum :: generate ( HACKATOM ) ;
229
230
let cache: Cache < MockApi , MockStorage , MockQuerier > =
230
231
unsafe { Cache :: new ( options. clone ( ) ) . unwrap ( ) } ;
231
232
// Load into memory
@@ -246,7 +247,7 @@ fn bench_cache(c: &mut Criterion) {
246
247
} ) ;
247
248
248
249
group. bench_function ( "instantiate from pinned memory" , |b| {
249
- let checksum = Checksum :: generate ( CONTRACT ) ;
250
+ let checksum = Checksum :: generate ( HACKATOM ) ;
250
251
let cache: Cache < MockApi , MockStorage , MockQuerier > =
251
252
unsafe { Cache :: new ( options. clone ( ) ) . unwrap ( ) } ;
252
253
// Load into pinned memory
@@ -267,11 +268,11 @@ fn bench_cache(c: &mut Criterion) {
267
268
group. finish ( ) ;
268
269
}
269
270
270
- pub fn bench_instance_threads ( c : & mut Criterion ) {
271
+ fn bench_instance_threads ( c : & mut Criterion ) {
271
272
c. bench_function ( "multi-threaded get_instance" , |b| {
272
273
let options = CacheOptions :: new (
273
274
TempDir :: new ( ) . unwrap ( ) . into_path ( ) ,
274
- capabilities_from_csv ( "iterator,staking" ) ,
275
+ capabilities_from_csv ( DEFAULT_CAPABILITIES ) ,
275
276
MEMORY_CACHE_SIZE ,
276
277
DEFAULT_MEMORY_LIMIT ,
277
278
) ;
@@ -290,10 +291,10 @@ pub fn bench_instance_threads(c: &mut Criterion) {
290
291
// Offset to the i32.const (0x41) 15731626 (0xf00baa) (unsigned leb128 encoded) instruction
291
292
// data we want to replace
292
293
let query_int_data = b"\x41 \xaa \x97 \xc0 \x07 " ;
293
- let offset = find_subsequence ( CONTRACT , query_int_data) . unwrap ( ) + 1 ;
294
+ let offset = find_subsequence ( HACKATOM , query_int_data) . unwrap ( ) + 1 ;
294
295
295
296
let mut leb128_buf = [ 0 ; 4 ] ;
296
- let mut contract = CONTRACT . to_vec ( ) ;
297
+ let mut contract = HACKATOM . to_vec ( ) ;
297
298
298
299
let mut random_checksum = || {
299
300
let mut writable = & mut leb128_buf[ ..] ;
@@ -352,24 +353,127 @@ pub fn bench_instance_threads(c: &mut Criterion) {
352
353
} ) ;
353
354
}
354
355
355
- fn make_config ( ) -> Criterion {
356
+ fn bench_combined ( c : & mut Criterion ) {
357
+ let mut group = c. benchmark_group ( "Combined" ) ;
358
+
359
+ let options = CacheOptions :: new (
360
+ TempDir :: new ( ) . unwrap ( ) . into_path ( ) ,
361
+ capabilities_from_csv ( "cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,iterator,staking" ) ,
362
+ MEMORY_CACHE_SIZE ,
363
+ DEFAULT_MEMORY_LIMIT ,
364
+ ) ;
365
+
366
+ // Store contracts for all benchmarks in this group
367
+ let checksum: Checksum = {
368
+ let cache: Cache < MockApi , MockStorage , MockQuerier > =
369
+ unsafe { Cache :: new ( options. clone ( ) ) . unwrap ( ) } ;
370
+ cache. save_wasm ( CYBERPUNK ) . unwrap ( )
371
+ } ;
372
+
373
+ group. bench_function ( "get instance from fs cache and execute" , |b| {
374
+ let mut non_memcache = options. clone ( ) ;
375
+ non_memcache. memory_cache_size = Size :: kibi ( 0 ) ;
376
+
377
+ let cache: Cache < MockApi , MockStorage , MockQuerier > =
378
+ unsafe { Cache :: new ( non_memcache) . unwrap ( ) } ;
379
+
380
+ b. iter ( || {
381
+ let mut instance = cache
382
+ . get_instance ( & checksum, mock_backend ( & [ ] ) , DEFAULT_INSTANCE_OPTIONS )
383
+ . unwrap ( ) ;
384
+ assert_eq ! ( cache. stats( ) . hits_pinned_memory_cache, 0 ) ;
385
+ assert_eq ! ( cache. stats( ) . hits_memory_cache, 0 ) ;
386
+ assert ! ( cache. stats( ) . hits_fs_cache >= 1 ) ;
387
+ assert_eq ! ( cache. stats( ) . misses, 0 ) ;
388
+
389
+ let info = mock_info ( "guest" , & [ ] ) ;
390
+ let msg = br#"{"noop":{}}"# ;
391
+ let contract_result =
392
+ call_execute :: < _ , _ , _ , Empty > ( & mut instance, & mock_env ( ) , & info, msg) . unwrap ( ) ;
393
+ contract_result. into_result ( ) . unwrap ( ) ;
394
+ } ) ;
395
+ } ) ;
396
+
397
+ group. bench_function ( "get instance from memory cache and execute" , |b| {
398
+ let cache: Cache < MockApi , MockStorage , MockQuerier > =
399
+ unsafe { Cache :: new ( options. clone ( ) ) . unwrap ( ) } ;
400
+
401
+ // Load into memory
402
+ cache
403
+ . get_instance ( & checksum, mock_backend ( & [ ] ) , DEFAULT_INSTANCE_OPTIONS )
404
+ . unwrap ( ) ;
405
+
406
+ b. iter ( || {
407
+ let backend = mock_backend ( & [ ] ) ;
408
+ let mut instance = cache
409
+ . get_instance ( & checksum, backend, DEFAULT_INSTANCE_OPTIONS )
410
+ . unwrap ( ) ;
411
+ assert_eq ! ( cache. stats( ) . hits_pinned_memory_cache, 0 ) ;
412
+ assert ! ( cache. stats( ) . hits_memory_cache >= 1 ) ;
413
+ assert_eq ! ( cache. stats( ) . hits_fs_cache, 1 ) ;
414
+ assert_eq ! ( cache. stats( ) . misses, 0 ) ;
415
+
416
+ let info = mock_info ( "guest" , & [ ] ) ;
417
+ let msg = br#"{"noop":{}}"# ;
418
+ let contract_result =
419
+ call_execute :: < _ , _ , _ , Empty > ( & mut instance, & mock_env ( ) , & info, msg) . unwrap ( ) ;
420
+ contract_result. into_result ( ) . unwrap ( ) ;
421
+ } ) ;
422
+ } ) ;
423
+
424
+ group. bench_function ( "get instance from pinned memory and execute" , |b| {
425
+ let cache: Cache < MockApi , MockStorage , MockQuerier > =
426
+ unsafe { Cache :: new ( options. clone ( ) ) . unwrap ( ) } ;
427
+
428
+ // Load into pinned memory
429
+ cache. pin ( & checksum) . unwrap ( ) ;
430
+
431
+ b. iter ( || {
432
+ let backend = mock_backend ( & [ ] ) ;
433
+ let mut instance = cache
434
+ . get_instance ( & checksum, backend, DEFAULT_INSTANCE_OPTIONS )
435
+ . unwrap ( ) ;
436
+ assert_eq ! ( cache. stats( ) . hits_memory_cache, 0 ) ;
437
+ assert ! ( cache. stats( ) . hits_pinned_memory_cache >= 1 ) ;
438
+ assert_eq ! ( cache. stats( ) . hits_fs_cache, 1 ) ;
439
+ assert_eq ! ( cache. stats( ) . misses, 0 ) ;
440
+
441
+ let info = mock_info ( "guest" , & [ ] ) ;
442
+ let msg = br#"{"noop":{}}"# ;
443
+ let contract_result =
444
+ call_execute :: < _ , _ , _ , Empty > ( & mut instance, & mock_env ( ) , & info, msg) . unwrap ( ) ;
445
+ contract_result. into_result ( ) . unwrap ( ) ;
446
+ } ) ;
447
+ } ) ;
448
+
449
+ group. finish ( ) ;
450
+ }
451
+
452
+ fn make_config ( measurement_time_s : u64 ) -> Criterion {
356
453
Criterion :: default ( )
357
454
. without_plots ( )
358
- . measurement_time ( Duration :: new ( 10 , 0 ) )
455
+ . measurement_time ( Duration :: new ( measurement_time_s , 0 ) )
359
456
. sample_size ( 12 )
360
457
. configure_from_args ( )
361
458
}
362
459
363
460
criterion_group ! (
364
461
name = instance;
365
- config = make_config( ) ;
462
+ config = make_config( 8 ) ;
366
463
targets = bench_instance
367
464
) ;
368
465
criterion_group ! (
369
466
name = cache;
370
- config = make_config( ) ;
467
+ config = make_config( 8 ) ;
371
468
targets = bench_cache
372
469
) ;
470
+ // Combines loading module from cache, instantiating it and executing the instance.
471
+ // This is what every call in libwasmvm does.
472
+ criterion_group ! (
473
+ name = combined;
474
+ config = make_config( 5 ) ;
475
+ targets = bench_combined
476
+ ) ;
373
477
criterion_group ! (
374
478
name = multi_threaded_instance;
375
479
config = Criterion :: default ( )
@@ -379,4 +483,4 @@ criterion_group!(
379
483
. configure_from_args( ) ;
380
484
targets = bench_instance_threads
381
485
) ;
382
- criterion_main ! ( instance, cache, multi_threaded_instance) ;
486
+ criterion_main ! ( instance, cache, combined , multi_threaded_instance) ;
0 commit comments