Optimize aligned memory used by the runtime (#17324)
This commit is contained in:
parent
e7073ecab1
commit
477898f682
|
@ -5508,9 +5508,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "solana_rbpf"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcec120278017a67e2dd98494dfdd8e565f53f1d05ab558d1656c369c5dd95e"
|
||||
checksum = "debbc13545a1d972955a4fd3014e7c9d6d81da16c3626ee5f64bf3aa619548f8"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"combine",
|
||||
|
|
|
@ -38,7 +38,7 @@ solana-config-program = { path = "../programs/config", version = "=1.7.0" }
|
|||
solana-faucet = { path = "../faucet", version = "=1.7.0" }
|
||||
solana-logger = { path = "../logger", version = "=1.7.0" }
|
||||
solana-net-utils = { path = "../net-utils", version = "=1.7.0" }
|
||||
solana_rbpf = "=0.2.8"
|
||||
solana_rbpf = "=0.2.9"
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "=1.7.0" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.7.0" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.7.0" }
|
||||
|
|
|
@ -3637,9 +3637,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "solana_rbpf"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcec120278017a67e2dd98494dfdd8e565f53f1d05ab558d1656c369c5dd95e"
|
||||
checksum = "debbc13545a1d972955a4fd3014e7c9d6d81da16c3626ee5f64bf3aa619548f8"
|
||||
dependencies = [
|
||||
"byteorder 1.3.4",
|
||||
"combine",
|
||||
|
|
|
@ -30,7 +30,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.7.0" }
|
|||
solana-cli-output = { path = "../../cli-output", version = "=1.7.0" }
|
||||
solana-logger = { path = "../../logger", version = "=1.7.0" }
|
||||
solana-measure = { path = "../../measure", version = "=1.7.0" }
|
||||
solana_rbpf = "=0.2.8"
|
||||
solana_rbpf = "=0.2.9"
|
||||
solana-runtime = { path = "../../runtime", version = "=1.7.0" }
|
||||
solana-sdk = { path = "../../sdk", version = "=1.7.0" }
|
||||
solana-transaction-status = { path = "../../transaction-status", version = "=1.7.0" }
|
||||
|
|
|
@ -20,7 +20,7 @@ sha3 = "0.9.1"
|
|||
solana-measure = { path = "../../measure", version = "=1.7.0" }
|
||||
solana-runtime = { path = "../../runtime", version = "=1.7.0" }
|
||||
solana-sdk = { path = "../../sdk", version = "=1.7.0" }
|
||||
solana_rbpf = "=0.2.8"
|
||||
solana_rbpf = "=0.2.9"
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
|
@ -148,7 +148,7 @@ pub fn create_vm<'a>(
|
|||
parameter_bytes: &mut [u8],
|
||||
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(loader_id, &mut vm, invoke_context, heap)?;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -2689,7 +2689,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(),
|
||||
|
@ -2716,7 +2716,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(),
|
||||
|
@ -2742,7 +2742,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(),
|
||||
|
@ -2769,7 +2769,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(),
|
||||
|
@ -2810,7 +2810,6 @@ mod tests {
|
|||
let bytes1 = "Gaggablaghblagh!";
|
||||
let bytes2 = "flurbos";
|
||||
|
||||
// lint warns field addr and len "never read"
|
||||
#[allow(dead_code)]
|
||||
struct MockSlice {
|
||||
pub addr: u64,
|
||||
|
|
Loading…
Reference in New Issue