Skip to content
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

feat: optimize allocations in writable CoW accounts #4846

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,6 @@ fn create_vm<'a, 'b>(
.touch(index_in_transaction as IndexOfAccount)
.map_err(|_| ())?;

if account.is_shared() {
// See BorrowedAccount::make_data_mut() as to why we reserve extra
// MAX_PERMITTED_DATA_INCREASE bytes here.
account.reserve(MAX_PERMITTED_DATA_INCREASE);
}
Ok(account.data_as_mut_slice().as_mut_ptr() as u64)
})),
)?;
Expand Down
7 changes: 7 additions & 0 deletions programs/bpf_loader/src/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,13 @@ fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
borrowed_account.set_data_length(post_len)?;
let allocated_bytes = post_len.saturating_sub(pre_len);
if allocated_bytes > 0 {
// Just in time resize of data field within the internal AccountSharedData
//
// NOTE: this is an optimization for CoW account mappings, where the account's
// data is not immediately resized with an extra MAX_PERMITTED_DATA_INCREASE,
// but if the realloc did occur (and this branch was taken) then we need to reserve
// max permitted amount of extra space so the subsequent code will work correctly
borrowed_account.reserve(MAX_PERMITTED_DATA_INCREASE)?;
borrowed_account
.get_data_mut()?
.get_mut(pre_len..pre_len.saturating_add(allocated_bytes))
Expand Down
10 changes: 6 additions & 4 deletions sdk/transaction-context/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,12 @@ impl BorrowedAccount<'_> {
// memory that holds the account but it doesn't actually change content
// nor length of the account.
self.make_data_mut();
self.account.reserve(additional);
// NOTE: we don't call reserve unnecessarily, as the first call to make_data_mut
// has already resized the data to an extra MAX_PERMITTED_DATA_INCREASE bytes
if additional > MAX_PERMITTED_DATA_INCREASE {
self.account
.reserve(additional.saturating_sub(MAX_PERMITTED_DATA_INCREASE));
}

Ok(())
}
Expand Down Expand Up @@ -1004,9 +1009,6 @@ impl BorrowedAccount<'_> {
// buffer with MAX_PERMITTED_DATA_INCREASE capacity so that if the
// transaction reallocs, we don't have to copy the whole account data a
// second time to fullfill the realloc.
//
// NOTE: The account memory region CoW code in bpf_loader::create_vm() implements the same
// logic and must be kept in sync.
if self.account.is_shared() {
self.account.reserve(MAX_PERMITTED_DATA_INCREASE);
}
Expand Down
Loading