Skip to content

Commit 8b6b2a4

Browse files
authored
Merge pull request #1998 from CosmWasm/add-noop
Add noop method to cyberpunk testing contract
2 parents cc059dc + 1478603 commit 8b6b2a4

File tree

10 files changed

+174
-30
lines changed

10 files changed

+174
-30
lines changed

.circleci/config.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ workflows:
8484
- main
8585
- /^[0-9]+\.[0-9]+$/
8686
# Add your branch here if benchmarking matters to your work
87-
- fix-benchmarking
88-
- w3
87+
- add-noop
8988
- coverage
9089
deploy:
9190
jobs:

contracts/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ docker run --rm -v "$(pwd)":/code \
6464
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
6565
cosmwasm/optimizer:0.15.0 ./contracts/crypto-verify
6666

67+
docker run --rm -v "$(pwd)":/code \
68+
--mount type=volume,source="devcontract_cache_cyberpunk",target=/target \
69+
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
70+
cosmwasm/optimizer:0.15.0 ./contracts/cyberpunk
71+
6772
docker run --rm -v "$(pwd)":/code \
6873
--mount type=volume,source="devcontract_cache_floaty",target=/target \
6974
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \

contracts/cyberpunk/schema/cyberpunk.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,20 @@
179179
}
180180
},
181181
"additionalProperties": false
182+
},
183+
{
184+
"description": "Does nothing. This can be used for baseline contract execution performance measurements.",
185+
"type": "object",
186+
"required": [
187+
"noop"
188+
],
189+
"properties": {
190+
"noop": {
191+
"type": "object",
192+
"additionalProperties": false
193+
}
194+
},
195+
"additionalProperties": false
182196
}
183197
]
184198
},

contracts/cyberpunk/schema/raw/execute.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@
169169
}
170170
},
171171
"additionalProperties": false
172+
},
173+
{
174+
"description": "Does nothing. This can be used for baseline contract execution performance measurements.",
175+
"type": "object",
176+
"required": [
177+
"noop"
178+
],
179+
"properties": {
180+
"noop": {
181+
"type": "object",
182+
"additionalProperties": false
183+
}
184+
},
185+
"additionalProperties": false
172186
}
173187
]
174188
}

contracts/cyberpunk/src/contract.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub fn execute(
3939
Unreachable {} => execute_unreachable(),
4040
MirrorEnv {} => execute_mirror_env(env),
4141
Debug {} => execute_debug(deps.api),
42+
Noop {} => execute_noop(),
4243
}
4344
}
4445

@@ -178,6 +179,10 @@ fn execute_debug(api: &dyn Api) -> Result<Response, ContractError> {
178179
Ok(Response::default())
179180
}
180181

182+
fn execute_noop() -> Result<Response, ContractError> {
183+
Ok(Response::new())
184+
}
185+
181186
#[entry_point]
182187
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<QueryResponse> {
183188
use QueryMsg::*;

contracts/cyberpunk/src/msg.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub enum ExecuteMsg {
3030
MirrorEnv {},
3131
/// Does a bit of work and calls debug
3232
Debug {},
33+
/// Does nothing. This can be used for baseline contract execution performance measurements.
34+
Noop {},
3335
}
3436

3537
#[cw_serde]

packages/vm/benches/main.rs

Lines changed: 128 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ const MEMORY_CACHE_SIZE: Size = Size::mebi(200);
3030
const INSTANTIATION_THREADS: usize = 128;
3131
const CONTRACTS: u64 = 10;
3232

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");
3435
static CYBERPUNK: &[u8] = include_bytes!("../testdata/cyberpunk.wasm");
3536

3637
fn bench_instance(c: &mut Criterion) {
@@ -41,7 +42,7 @@ fn bench_instance(c: &mut Criterion) {
4142
let backend = mock_backend(&[]);
4243
let (instance_options, memory_limit) = mock_instance_options();
4344
let _instance =
44-
Instance::from_code(CONTRACT, backend, instance_options, memory_limit).unwrap();
45+
Instance::from_code(HACKATOM, backend, instance_options, memory_limit).unwrap();
4546
});
4647
});
4748

@@ -51,7 +52,7 @@ fn bench_instance(c: &mut Criterion) {
5152
gas_limit: HIGH_GAS_LIMIT,
5253
};
5354
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();
5556

5657
b.iter(|| {
5758
let info = mock_info(&instance.api().addr_make("creator"), &coins(1000, "earth"));
@@ -75,7 +76,7 @@ fn bench_instance(c: &mut Criterion) {
7576
gas_limit: HIGH_GAS_LIMIT,
7677
};
7778
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();
7980

8081
let info = mock_info(&instance.api().addr_make("creator"), &coins(1000, "earth"));
8182
let verifier = instance.api().addr_make("verifies");
@@ -129,7 +130,7 @@ fn bench_cache(c: &mut Criterion) {
129130

130131
let options = CacheOptions::new(
131132
TempDir::new().unwrap().into_path(),
132-
capabilities_from_csv("iterator,staking"),
133+
capabilities_from_csv(DEFAULT_CAPABILITIES),
133134
MEMORY_CACHE_SIZE,
134135
DEFAULT_MEMORY_LIMIT,
135136
);
@@ -139,15 +140,15 @@ fn bench_cache(c: &mut Criterion) {
139140
unsafe { Cache::new(options.clone()).unwrap() };
140141

141142
b.iter(|| {
142-
let result = cache.save_wasm(CONTRACT);
143+
let result = cache.save_wasm(HACKATOM);
143144
assert!(result.is_ok());
144145
});
145146
});
146147

147148
group.bench_function("load wasm", |b| {
148149
let cache: Cache<MockApi, MockStorage, MockQuerier> =
149150
unsafe { Cache::new(options.clone()).unwrap() };
150-
let checksum = cache.save_wasm(CONTRACT).unwrap();
151+
let checksum = cache.save_wasm(HACKATOM).unwrap();
151152

152153
b.iter(|| {
153154
let result = cache.load_wasm(&checksum);
@@ -160,7 +161,7 @@ fn bench_cache(c: &mut Criterion) {
160161
let mut cache: Cache<MockApi, MockStorage, MockQuerier> =
161162
unsafe { Cache::new(options).unwrap() };
162163
cache.set_module_unchecked(true);
163-
let checksum = cache.save_wasm(CONTRACT).unwrap();
164+
let checksum = cache.save_wasm(HACKATOM).unwrap();
164165

165166
b.iter(|| {
166167
let result = cache.load_wasm(&checksum);
@@ -171,7 +172,7 @@ fn bench_cache(c: &mut Criterion) {
171172
group.bench_function("analyze", |b| {
172173
let cache: Cache<MockApi, MockStorage, MockQuerier> =
173174
unsafe { Cache::new(options.clone()).unwrap() };
174-
let checksum = cache.save_wasm(CONTRACT).unwrap();
175+
let checksum = cache.save_wasm(HACKATOM).unwrap();
175176

176177
b.iter(|| {
177178
let result = cache.analyze(&checksum);
@@ -182,13 +183,13 @@ fn bench_cache(c: &mut Criterion) {
182183
group.bench_function("instantiate from fs", |b| {
183184
let non_memcache = CacheOptions::new(
184185
TempDir::new().unwrap().into_path(),
185-
capabilities_from_csv("iterator,staking"),
186+
capabilities_from_csv(DEFAULT_CAPABILITIES),
186187
Size::new(0),
187188
DEFAULT_MEMORY_LIMIT,
188189
);
189190
let cache: Cache<MockApi, MockStorage, MockQuerier> =
190191
unsafe { Cache::new(non_memcache).unwrap() };
191-
let checksum = cache.save_wasm(CONTRACT).unwrap();
192+
let checksum = cache.save_wasm(HACKATOM).unwrap();
192193

193194
b.iter(|| {
194195
let _ = cache
@@ -204,14 +205,14 @@ fn bench_cache(c: &mut Criterion) {
204205
group.bench_function("instantiate from fs unchecked", |b| {
205206
let non_memcache = CacheOptions::new(
206207
TempDir::new().unwrap().into_path(),
207-
capabilities_from_csv("iterator,staking"),
208+
capabilities_from_csv(DEFAULT_CAPABILITIES),
208209
Size::new(0),
209210
DEFAULT_MEMORY_LIMIT,
210211
);
211212
let mut cache: Cache<MockApi, MockStorage, MockQuerier> =
212213
unsafe { Cache::new(non_memcache).unwrap() };
213214
cache.set_module_unchecked(true);
214-
let checksum = cache.save_wasm(CONTRACT).unwrap();
215+
let checksum = cache.save_wasm(HACKATOM).unwrap();
215216

216217
b.iter(|| {
217218
let _ = cache
@@ -225,7 +226,7 @@ fn bench_cache(c: &mut Criterion) {
225226
});
226227

227228
group.bench_function("instantiate from memory", |b| {
228-
let checksum = Checksum::generate(CONTRACT);
229+
let checksum = Checksum::generate(HACKATOM);
229230
let cache: Cache<MockApi, MockStorage, MockQuerier> =
230231
unsafe { Cache::new(options.clone()).unwrap() };
231232
// Load into memory
@@ -246,7 +247,7 @@ fn bench_cache(c: &mut Criterion) {
246247
});
247248

248249
group.bench_function("instantiate from pinned memory", |b| {
249-
let checksum = Checksum::generate(CONTRACT);
250+
let checksum = Checksum::generate(HACKATOM);
250251
let cache: Cache<MockApi, MockStorage, MockQuerier> =
251252
unsafe { Cache::new(options.clone()).unwrap() };
252253
// Load into pinned memory
@@ -267,11 +268,11 @@ fn bench_cache(c: &mut Criterion) {
267268
group.finish();
268269
}
269270

270-
pub fn bench_instance_threads(c: &mut Criterion) {
271+
fn bench_instance_threads(c: &mut Criterion) {
271272
c.bench_function("multi-threaded get_instance", |b| {
272273
let options = CacheOptions::new(
273274
TempDir::new().unwrap().into_path(),
274-
capabilities_from_csv("iterator,staking"),
275+
capabilities_from_csv(DEFAULT_CAPABILITIES),
275276
MEMORY_CACHE_SIZE,
276277
DEFAULT_MEMORY_LIMIT,
277278
);
@@ -290,10 +291,10 @@ pub fn bench_instance_threads(c: &mut Criterion) {
290291
// Offset to the i32.const (0x41) 15731626 (0xf00baa) (unsigned leb128 encoded) instruction
291292
// data we want to replace
292293
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;
294295

295296
let mut leb128_buf = [0; 4];
296-
let mut contract = CONTRACT.to_vec();
297+
let mut contract = HACKATOM.to_vec();
297298

298299
let mut random_checksum = || {
299300
let mut writable = &mut leb128_buf[..];
@@ -352,24 +353,127 @@ pub fn bench_instance_threads(c: &mut Criterion) {
352353
});
353354
}
354355

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 {
356453
Criterion::default()
357454
.without_plots()
358-
.measurement_time(Duration::new(10, 0))
455+
.measurement_time(Duration::new(measurement_time_s, 0))
359456
.sample_size(12)
360457
.configure_from_args()
361458
}
362459

363460
criterion_group!(
364461
name = instance;
365-
config = make_config();
462+
config = make_config(8);
366463
targets = bench_instance
367464
);
368465
criterion_group!(
369466
name = cache;
370-
config = make_config();
467+
config = make_config(8);
371468
targets = bench_cache
372469
);
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+
);
373477
criterion_group!(
374478
name = multi_threaded_instance;
375479
config = Criterion::default()
@@ -379,4 +483,4 @@ criterion_group!(
379483
.configure_from_args();
380484
targets = bench_instance_threads
381485
);
382-
criterion_main!(instance, cache, multi_threaded_instance);
486+
criterion_main!(instance, cache, combined, multi_threaded_instance);

0 commit comments

Comments
 (0)