Skip to content

Commit 10187cf

Browse files
committed
lock cache to support parallel
1 parent 37086fe commit 10187cf

File tree

2 files changed

+80
-51
lines changed

2 files changed

+80
-51
lines changed

packages/vm/src/cache.rs

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
use std::{
2+
borrow::{BorrowMut},
3+
sync::{Arc, RwLock},
4+
};
5+
16
use crate::checksum::Checksum;
27
use crate::error::Error;
38

@@ -42,44 +47,57 @@ pub struct CacheOptions {
4247
}
4348

4449
pub struct Cache {
45-
memory_cache: InMemoryCache,
50+
memory_cache: Arc<RwLock<InMemoryCache>>,
4651
stats: Stats,
4752
}
4853

4954
impl Cache {
5055
pub fn new(options: CacheOptions) -> Self {
5156
let CacheOptions { cache_size } = options;
5257

53-
Self { memory_cache: InMemoryCache::new(cache_size), stats: Stats::new() }
58+
Self {
59+
memory_cache: Arc::new(RwLock::new(InMemoryCache::new(cache_size))),
60+
stats: Stats::new(),
61+
}
5462
}
5563

5664
pub fn stats(&self) -> &Stats {
5765
&self.stats
5866
}
5967

68+
fn with_in_memory_cache<C, R>(&mut self, callback: C) -> R
69+
where
70+
C: FnOnce(&mut InMemoryCache, &mut Stats) -> R,
71+
{
72+
let mut guard = self.memory_cache.as_ref().write().unwrap();
73+
let in_memory_cache = guard.borrow_mut();
74+
callback(in_memory_cache, &mut self.stats)
75+
}
76+
6077
pub fn get_instance(
6178
&mut self,
6279
wasm: &[u8],
6380
store: &Store,
6481
import_object: &wasmer::ImportObject,
6582
) -> Result<wasmer::Instance, Error> {
6683
let checksum = Checksum::generate(wasm);
67-
68-
// lookup cache
69-
if let Some(module) = self.memory_cache.load(&checksum) {
70-
self.stats.hits += 1;
71-
return Ok(Instance::new(&module, &import_object).unwrap());
72-
}
73-
self.stats.misses += 1;
74-
75-
// recompile
76-
let module = Module::new(store, &wasm).map_err(|_| Error::InstantiationError)?;
77-
let instance =
84+
self.with_in_memory_cache(|in_memory_cache, stats| {
85+
// lookup cache
86+
if let Some(module) = in_memory_cache.load(&checksum) {
87+
stats.hits += 1;
88+
return Ok(Instance::new(&module, &import_object).unwrap());
89+
}
90+
stats.misses += 1;
91+
92+
// recompile
93+
let module = Module::new(store, &wasm).map_err(|_| Error::InstantiationError)?;
94+
let instance =
7895
Instance::new(&module, &import_object).map_err(|_| Error::InstantiationError)?;
79-
80-
self.memory_cache.store(&checksum, module);
81-
82-
Ok(instance)
96+
97+
in_memory_cache.store(&checksum, module);
98+
99+
Ok(instance)
100+
})
83101
}
84102
}
85103

packages/vm/src/imports.rs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,58 @@ use wasmer::{imports, Function, ImportObject, Store};
55

66
use owasm_crypto::ecvrf;
77

8+
const IMPORTED_FUNCTION_GAS: u64 = 750_000_000;
9+
const ECVRF_VERIFY_GAS: u64 = 7_500_000_000_000;
10+
811
fn require_mem_range(max_range: usize, require_range: usize) -> Result<(), Error> {
912
if max_range < require_range {
1013
return Err(Error::MemoryOutOfBoundError);
1114
}
1215
Ok(())
1316
}
1417

18+
fn read_memory<Q>(env: &Environment<Q>, ptr: i64, len: i64) -> Result<Vec<u8>, Error>
19+
where
20+
Q: Querier + 'static,
21+
{
22+
let memory = env.memory()?;
23+
require_mem_range(memory.size().bytes().0, (ptr + len) as usize)?;
24+
Ok(memory.view()[ptr as usize..(ptr + len) as usize].iter().map(|cell| cell.get()).collect())
25+
}
26+
27+
fn write_memory<Q>(env: &Environment<Q>, ptr: i64, data: Vec<u8>) -> Result<i64, Error>
28+
where
29+
Q: Querier + 'static,
30+
{
31+
let memory = env.memory()?;
32+
require_mem_range(memory.size().bytes().0, (ptr + data.len() as i64) as usize)?;
33+
for (idx, byte) in data.iter().enumerate() {
34+
memory.view()[ptr as usize + idx].set(*byte);
35+
}
36+
Ok(data.len() as i64)
37+
}
38+
39+
fn calculate_read_memory_gas(len: i64) -> u64 {
40+
1_000_000_000 + (len as u64) * 1_500_000
41+
}
42+
43+
fn calculate_write_memory_gas(len: usize) -> u64 {
44+
2_250_000_000 + (len as u64) * 30_000_000
45+
}
46+
1547
fn do_gas<Q>(env: &Environment<Q>, _gas: u32) -> Result<(), Error>
1648
where
1749
Q: Querier + 'static,
1850
{
19-
env.decrease_gas_left(750_000_000)?;
51+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS)?;
2052
Ok(())
2153
}
2254

2355
fn do_get_span_size<Q>(env: &Environment<Q>) -> Result<i64, Error>
2456
where
2557
Q: Querier + 'static,
2658
{
27-
env.decrease_gas_left(750_000_000)?;
59+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS)?;
2860
Ok(env.with_querier_from_context(|querier| querier.get_span_size()))
2961
}
3062

@@ -40,7 +72,7 @@ where
4072
return Err(Error::SpanTooSmallError);
4173
}
4274

43-
env.decrease_gas_left(3_000_000_000 + (data.len() as u64) * 30_000_000)?;
75+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS + calculate_write_memory_gas(data.len()))?;
4476
write_memory(env, ptr, data)
4577
})
4678
}
@@ -55,7 +87,7 @@ where
5587
if len > span_size {
5688
return Err(Error::SpanTooSmallError);
5789
}
58-
env.decrease_gas_left(1_750_000_000 + (len as u64) * 1_500_000)?;
90+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS + calculate_read_memory_gas(len))?;
5991

6092
let data: Vec<u8> = read_memory(env, ptr, len)?;
6193
querier.set_return_data(&data)
@@ -66,39 +98,39 @@ fn do_get_ask_count<Q>(env: &Environment<Q>) -> Result<i64, Error>
6698
where
6799
Q: Querier + 'static,
68100
{
69-
env.decrease_gas_left(750_000_000)?;
101+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS)?;
70102
Ok(env.with_querier_from_context(|querier| querier.get_ask_count()))
71103
}
72104

73105
fn do_get_min_count<Q>(env: &Environment<Q>) -> Result<i64, Error>
74106
where
75107
Q: Querier + 'static,
76108
{
77-
env.decrease_gas_left(750_000_000)?;
109+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS)?;
78110
Ok(env.with_querier_from_context(|querier| querier.get_min_count()))
79111
}
80112

81113
fn do_get_prepare_time<Q>(env: &Environment<Q>) -> Result<i64, Error>
82114
where
83115
Q: Querier + 'static,
84116
{
85-
env.decrease_gas_left(750_000_000)?;
117+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS)?;
86118
Ok(env.with_querier_from_context(|querier| querier.get_prepare_time()))
87119
}
88120

89121
fn do_get_execute_time<Q>(env: &Environment<Q>) -> Result<i64, Error>
90122
where
91123
Q: Querier + 'static,
92124
{
93-
env.decrease_gas_left(750_000_000)?;
125+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS)?;
94126
env.with_querier_from_context(|querier| querier.get_execute_time())
95127
}
96128

97129
fn do_get_ans_count<Q>(env: &Environment<Q>) -> Result<i64, Error>
98130
where
99131
Q: Querier + 'static,
100132
{
101-
env.decrease_gas_left(750_000_000)?;
133+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS)?;
102134
env.with_querier_from_context(|querier| querier.get_ans_count())
103135
}
104136

@@ -118,7 +150,7 @@ where
118150
if len > span_size {
119151
return Err(Error::SpanTooSmallError);
120152
}
121-
env.decrease_gas_left(1_750_000_000 + (len as u64) * 1_500_000)?;
153+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS + calculate_read_memory_gas(len))?;
122154

123155
let data: Vec<u8> = read_memory(env, ptr, len)?;
124156
querier.ask_external_data(eid, did, &data)
@@ -129,7 +161,7 @@ fn do_get_external_data_status<Q>(env: &Environment<Q>, eid: i64, vid: i64) -> R
129161
where
130162
Q: Querier + 'static,
131163
{
132-
env.decrease_gas_left(750_000_000)?;
164+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS)?;
133165
env.with_querier_from_context(|querier| querier.get_external_data_status(eid, vid))
134166
}
135167

@@ -150,32 +182,11 @@ where
150182
return Err(Error::SpanTooSmallError);
151183
}
152184

153-
env.decrease_gas_left(3_000_000_000 + (data.len() as u64) * 30_000_000)?;
185+
env.decrease_gas_left(IMPORTED_FUNCTION_GAS + calculate_write_memory_gas(data.len()))?;
154186
write_memory(env, ptr, data)
155187
})
156188
}
157189

158-
fn read_memory<Q>(env: &Environment<Q>, ptr: i64, len: i64) -> Result<Vec<u8>, Error>
159-
where
160-
Q: Querier + 'static,
161-
{
162-
let memory = env.memory()?;
163-
require_mem_range(memory.size().bytes().0, (ptr + len) as usize)?;
164-
Ok(memory.view()[ptr as usize..(ptr + len) as usize].iter().map(|cell| cell.get()).collect())
165-
}
166-
167-
fn write_memory<Q>(env: &Environment<Q>, ptr: i64, data: Vec<u8>) -> Result<i64, Error>
168-
where
169-
Q: Querier + 'static,
170-
{
171-
let memory = env.memory()?;
172-
require_mem_range(memory.size().bytes().0, (ptr + data.len() as i64) as usize)?;
173-
for (idx, byte) in data.iter().enumerate() {
174-
memory.view()[ptr as usize + idx].set(*byte);
175-
}
176-
Ok(data.len() as i64)
177-
}
178-
179190
fn do_ecvrf_verify<Q>(
180191
env: &Environment<Q>,
181192
y_ptr: i64,
@@ -189,7 +200,7 @@ where
189200
Q: Querier + 'static,
190201
{
191202
// consume gas relatively to the function running time (~7.5ms)
192-
env.decrease_gas_left(7_500_000_000_000)?;
203+
env.decrease_gas_left(ECVRF_VERIFY_GAS)?;
193204
let y: Vec<u8> = read_memory(env, y_ptr, y_len)?;
194205
let pi: Vec<u8> = read_memory(env, pi_ptr, pi_len)?;
195206
let alpha: Vec<u8> = read_memory(env, alpha_ptr, alpha_len)?;

0 commit comments

Comments
 (0)