-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize interpreter::blockchain::{load_contract_code, code_copy
to read contract starting from offset
#847
base: master
Are you sure you want to change the base?
Changes from 10 commits
ab0cc7b
816390f
994008e
ded2cff
ccfbb61
ef32062
0280827
83a97ba
8c6ced6
bd00e21
010dd6f
d67dd77
470cd31
226330a
c6ae75e
5cfd978
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,6 +60,7 @@ use fuel_storage::{ | |
use fuel_tx::{ | ||
consts::BALANCE_ENTRY_SIZE, | ||
BlobId, | ||
Contract, | ||
ContractIdExt, | ||
DependentCost, | ||
Receipt, | ||
|
@@ -636,8 +637,12 @@ where | |
self.gas_cost, | ||
charge_len, | ||
)?; | ||
let contract = super::contract::contract(self.storage, &contract_id)?; | ||
let contract_bytes = contract.as_ref().as_ref(); | ||
|
||
let contract_buffer: Vec<u8> = load_contract_code_from_storage( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After reviewing this change, I see that we basically have the same code as before and allocate vectors in all cases. So basically, this change doesn't make a lot of sense=D The main problem is why we can't do the optimal implementation and copy directly into the memory - contract offset(and blob offset, since we have the same problem for blobs I think we need to extend the
Could you change this method to work with Also, it would be nice if you do the same for blobs as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the original idea was to have only one allocation. The only actual improvement in this PR as is now is fixing <MemoryStorage as StorageRead>::read`, which was panicking before due to slices of been different size being copied. Happy to extend the trait to read. I think it would be better to add a new function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine with the new method and with reworking the old one. I think changing the old one makes more sense because the compiler will help you identify places that also need to be updated in the code to avoid allocation of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, just to make sure: if we opt for modifying the |
||
self.storage, | ||
contract_len as usize, | ||
&contract_id, | ||
)?; | ||
|
||
let new_sp = ssp.saturating_add(length); | ||
self.memory.grow_stack(new_sp)?; | ||
|
@@ -654,7 +659,7 @@ where | |
copy_from_slice_zero_fill( | ||
self.memory, | ||
owner, | ||
contract_bytes, | ||
&contract_buffer, | ||
region_start, | ||
contract_offset, | ||
length, | ||
|
@@ -870,6 +875,28 @@ where | |
} | ||
} | ||
|
||
fn load_contract_code_from_storage<S>( | ||
storage: &S, | ||
contract_len: usize, | ||
contract_id: &ContractId, | ||
) -> Result<Vec<u8>, RuntimeError<<S as InterpreterStorage>::DataError>> | ||
where | ||
S: InterpreterStorage, | ||
{ | ||
let mut contract_buffer: Vec<u8> = alloc::vec![0u8; contract_len as usize]; | ||
storage | ||
.read_contract(&contract_id, &mut contract_buffer) | ||
.transpose() | ||
.ok_or(PanicReason::ContractNotFound)? | ||
.map_err(RuntimeError::Storage)?; | ||
|
||
if contract_buffer.len() != contract_len as usize { | ||
Err(PanicReason::ContractMismatch)? | ||
} else { | ||
Ok(contract_buffer) | ||
} | ||
} | ||
|
||
struct BurnCtx<'vm, S> { | ||
storage: &'vm mut S, | ||
context: &'vm Context, | ||
|
@@ -994,9 +1021,14 @@ where | |
self.memory.write(self.owner, dst_addr, length)?; | ||
self.input_contracts.check(&contract_id)?; | ||
|
||
let contract = super::contract::contract(self.storage, &contract_id)?; | ||
let contract_bytes = contract.as_ref().as_ref(); | ||
let contract_len = contract_bytes.len(); | ||
let contract_len = contract_size(self.storage, &contract_id)?; | ||
|
||
let mut contract_buffer = load_contract_code_from_storage( | ||
self.storage, | ||
contract_len as usize, | ||
&contract_id, | ||
)?; | ||
|
||
let charge_len = core::cmp::max(contract_len as u64, length); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We never read more than |
||
let profiler = ProfileGas { | ||
pc: self.pc.as_ref(), | ||
|
@@ -1016,7 +1048,7 @@ where | |
copy_from_slice_zero_fill( | ||
self.memory, | ||
self.owner, | ||
contract.as_ref().as_ref(), | ||
&contract_buffer, | ||
dst_addr, | ||
contract_offset, | ||
length, | ||
|
@@ -1112,13 +1144,11 @@ impl<'vm, S> CodeRootCtx<'vm, S> { | |
self.gas_cost, | ||
len as u64, | ||
)?; | ||
let root = self | ||
.storage | ||
.storage_contract(&contract_id) | ||
.transpose() | ||
.ok_or(PanicReason::ContractNotFound)? | ||
.map_err(RuntimeError::Storage)? | ||
.root(); | ||
|
||
let buf: Vec<u8> = | ||
load_contract_code_from_storage(self.storage, len as usize, &contract_id)?; | ||
|
||
let root = Contract::root_from_code(buf); | ||
|
||
self.memory.write_bytes(self.owner, a, *root)?; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused by this. There is no function called
contract_read
that is removed in these changes. And you added a call toread_contract
, which sounds like the same thing?