Skip to content

Commit

Permalink
Optimize aligned memory used by the runtime (backport #17324) (#17334)
Browse files Browse the repository at this point in the history
* Optimize aligned memory used by the runtime (#17324)

(cherry picked from commit 477898f)

# Conflicts:
#	cli/Cargo.toml
#	programs/bpf/Cargo.toml
#	programs/bpf_loader/Cargo.toml
#	programs/bpf_loader/src/syscalls.rs

* resolve conflicts

Co-authored-by: Jack May <jack@solana.com>
  • Loading branch information
mergify[bot] and jackcmay authored May 19, 2021
1 parent d2e98cb commit 0e9fe08
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 13 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ solana-config-program = { path = "../programs/config", version = "=1.6.10" }
solana-faucet = { path = "../faucet", version = "=1.6.10" }
solana-logger = { path = "../logger", version = "=1.6.10" }
solana-net-utils = { path = "../net-utils", version = "=1.6.10" }
solana_rbpf = "=0.2.8"
solana_rbpf = "=0.2.9"
solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.10" }
solana-sdk = { path = "../sdk", version = "=1.6.10" }
solana-stake-program = { path = "../programs/stake", version = "=1.6.10" }
Expand Down
4 changes: 2 additions & 2 deletions programs/bpf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion programs/bpf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.6.10" }
solana-cli-output = { path = "../../cli-output", version = "=1.6.10" }
solana-logger = { path = "../../logger", version = "=1.6.10" }
solana-measure = { path = "../../measure", version = "=1.6.10" }
solana_rbpf = "=0.2.8"
solana_rbpf = "=0.2.9"
solana-runtime = { path = "../../runtime", version = "=1.6.10" }
solana-sdk = { path = "../../sdk", version = "=1.6.10" }
solana-transaction-status = { path = "../../transaction-status", version = "=1.6.10" }
Expand Down
2 changes: 1 addition & 1 deletion programs/bpf_loader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ sha3 = "0.9.1"
solana-measure = { path = "../../measure", version = "=1.6.10" }
solana-runtime = { path = "../../runtime", version = "=1.6.10" }
solana-sdk = { path = "../../sdk", version = "=1.6.10" }
solana_rbpf = "=0.2.8"
solana_rbpf = "=0.2.9"
thiserror = "1.0"

[dev-dependencies]
Expand Down
141 changes: 141 additions & 0 deletions programs/bpf_loader/benches/serialization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#![feature(test)]

extern crate test;

use solana_bpf_loader_program::serialization::{
serialize_parameters_aligned, serialize_parameters_unaligned,
};
use solana_sdk::{
account::{Account, AccountSharedData},
bpf_loader,
};
use solana_sdk::{keyed_account::KeyedAccount, pubkey::Pubkey};
use std::cell::RefCell;
use test::Bencher;

fn create_inputs() -> (
Pubkey,
Vec<Pubkey>,
Vec<RefCell<AccountSharedData>>,
Vec<u8>,
) {
let program_id = solana_sdk::pubkey::new_rand();
let dup_key = solana_sdk::pubkey::new_rand();
let dup_key2 = solana_sdk::pubkey::new_rand();
let keys = vec![
dup_key,
dup_key,
solana_sdk::pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
dup_key2,
dup_key2,
solana_sdk::pubkey::new_rand(),
solana_sdk::pubkey::new_rand(),
];
let accounts = vec![
RefCell::new(AccountSharedData::from(Account {
lamports: 1,
data: vec![1u8, 2, 3, 4, 5],
owner: bpf_loader::id(),
executable: false,
rent_epoch: 100,
})),
// dup
RefCell::new(AccountSharedData::from(Account {
lamports: 1,
data: vec![1u8; 100000],
owner: bpf_loader::id(),
executable: false,
rent_epoch: 100,
})),
RefCell::new(AccountSharedData::from(Account {
lamports: 2,
data: vec![11u8; 100000],
owner: bpf_loader::id(),
executable: true,
rent_epoch: 200,
})),
RefCell::new(AccountSharedData::from(Account {
lamports: 3,
data: vec![],
owner: bpf_loader::id(),
executable: false,
rent_epoch: 3100,
})),
RefCell::new(AccountSharedData::from(Account {
lamports: 4,
data: vec![1u8; 100000],
owner: bpf_loader::id(),
executable: false,
rent_epoch: 100,
})),
// dup
RefCell::new(AccountSharedData::from(Account {
lamports: 4,
data: vec![1u8; 1000000],
owner: bpf_loader::id(),
executable: false,
rent_epoch: 100,
})),
RefCell::new(AccountSharedData::from(Account {
lamports: 5,
data: vec![11u8; 10000],
owner: bpf_loader::id(),
executable: true,
rent_epoch: 200,
})),
RefCell::new(AccountSharedData::from(Account {
lamports: 6,
data: vec![],
owner: bpf_loader::id(),
executable: false,
rent_epoch: 3100,
})),
];

let instruction_data = vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

(program_id, keys, accounts, instruction_data)
}

#[bench]
fn bench_serialize_unaligned(bencher: &mut Bencher) {
let (program_id, keys, accounts, instruction_data) = create_inputs();
let keyed_accounts: Vec<_> = keys
.iter()
.zip(&accounts)
.enumerate()
.map(|(i, (key, account))| {
if i <= accounts.len() / 2 {
KeyedAccount::new_readonly(&key, false, &account)
} else {
KeyedAccount::new(&key, false, &account)
}
})
.collect();
bencher.iter(|| {
let _ = serialize_parameters_unaligned(&program_id, &keyed_accounts, &instruction_data)
.unwrap();
});
}

#[bench]
fn bench_serialize_aligned(bencher: &mut Bencher) {
let (program_id, keys, accounts, instruction_data) = create_inputs();
let keyed_accounts: Vec<_> = keys
.iter()
.zip(&accounts)
.enumerate()
.map(|(i, (key, account))| {
if i <= accounts.len() / 2 {
KeyedAccount::new_readonly(&key, false, &account)
} else {
KeyedAccount::new(&key, false, &account)
}
})
.collect();
bencher.iter(|| {
let _ =
serialize_parameters_aligned(&program_id, &keyed_accounts, &instruction_data).unwrap();
});
}
2 changes: 1 addition & 1 deletion programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ pub fn create_vm<'a>(
parameter_accounts: &'a [KeyedAccount<'a>],
invoke_context: &'a mut dyn InvokeContext,
) -> Result<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
let heap = AlignedMemory::new(DEFAULT_HEAP_SIZE, HOST_ALIGN);
let heap = AlignedMemory::new_with_size(DEFAULT_HEAP_SIZE, HOST_ALIGN);
let heap_region = MemoryRegion::new_from_slice(heap.as_slice(), MM_HEAP_START, 0, true);
let mut vm = EbpfVm::new(program, parameter_bytes, &[heap_region])?;
syscalls::bind_syscall_context_objects(
Expand Down
2 changes: 1 addition & 1 deletion programs/bpf_loader/src/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ pub fn serialize_parameters_aligned(
.map_err(|_| InstructionError::InvalidArgument)?;
v.write_all(&keyed_account.try_account_ref()?.data())
.map_err(|_| InstructionError::InvalidArgument)?;
v.fill(
v.resize(
MAX_PERMITTED_DATA_INCREASE
+ (v.write_index() as *const u8).align_offset(align_of::<u128>()),
0,
Expand Down
9 changes: 5 additions & 4 deletions programs/bpf_loader/src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2701,7 +2701,7 @@ mod tests {
fn test_syscall_sol_alloc_free() {
// large alloc
{
let heap = AlignedMemory::new(100, HOST_ALIGN);
let heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
let memory_mapping = MemoryMapping::new::<UserError>(
vec![MemoryRegion::new_from_slice(
heap.as_slice(),
Expand All @@ -2728,7 +2728,7 @@ mod tests {
}
// many small unaligned allocs
{
let heap = AlignedMemory::new(100, HOST_ALIGN);
let heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
let memory_mapping = MemoryMapping::new::<UserError>(
vec![MemoryRegion::new_from_slice(
heap.as_slice(),
Expand All @@ -2754,7 +2754,7 @@ mod tests {
}
// many small aligned allocs
{
let heap = AlignedMemory::new(100, HOST_ALIGN);
let heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
let memory_mapping = MemoryMapping::new::<UserError>(
vec![MemoryRegion::new_from_slice(
heap.as_slice(),
Expand All @@ -2781,7 +2781,7 @@ mod tests {
// aligned allocs

fn check_alignment<T>() {
let heap = AlignedMemory::new(100, HOST_ALIGN);
let heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
let memory_mapping = MemoryMapping::new::<UserError>(
vec![MemoryRegion::new_from_slice(
heap.as_slice(),
Expand Down Expand Up @@ -2822,6 +2822,7 @@ mod tests {
let bytes1 = "Gaggablaghblagh!";
let bytes2 = "flurbos";

#[allow(dead_code)]
struct MockSlice {
pub addr: u64,
pub len: usize,
Expand Down

0 comments on commit 0e9fe08

Please sign in to comment.