Replaces MockInvokeContext by ThisInvokeContext in tests (#20881)
* Replaces MockInvokeContext by ThisInvokeContext in BpfLoader, SystemInstructionProcessor, CLIs, ConfigProcessor, StakeProcessor and VoteProcessor. * Finally, removes MockInvokeContext, MockComputeMeter and MockLogger. * Adjusts assert_instruction_count test. * Moves ThisInvokeContext to the program-runtime crate.
This commit is contained in:
committed by
GitHub
parent
0597594943
commit
7200c5106e
@@ -18,18 +18,18 @@ use solana_runtime::{
|
||||
genesis_utils::{create_genesis_config, GenesisConfigInfo},
|
||||
loader_utils::load_program,
|
||||
};
|
||||
use solana_program_runtime::invoke_context::with_mock_invoke_context;
|
||||
use solana_sdk::{
|
||||
account::AccountSharedData,
|
||||
bpf_loader,
|
||||
client::SyncClient,
|
||||
entrypoint::SUCCESS,
|
||||
instruction::{AccountMeta, Instruction},
|
||||
message::Message,
|
||||
process_instruction::{InvokeContext, MockComputeMeter, MockInvokeContext},
|
||||
process_instruction::InvokeContext,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
};
|
||||
use std::{cell::RefCell, env, fs::File, io::Read, mem, path::PathBuf, rc::Rc, sync::Arc};
|
||||
use std::{env, fs::File, io::Read, mem, path::PathBuf, sync::Arc};
|
||||
use test::Bencher;
|
||||
|
||||
/// BPF program file extension
|
||||
@@ -94,93 +94,73 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||
.write_u64::<LittleEndian>(ARMSTRONG_LIMIT)
|
||||
.unwrap();
|
||||
inner_iter.write_u64::<LittleEndian>(0).unwrap();
|
||||
|
||||
let loader_id = bpf_loader::id();
|
||||
let program_id = solana_sdk::pubkey::new_rand();
|
||||
let accounts = [
|
||||
(
|
||||
program_id,
|
||||
RefCell::new(AccountSharedData::new(0, 0, &loader_id)),
|
||||
),
|
||||
(
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
RefCell::new(AccountSharedData::new(
|
||||
1,
|
||||
10000001,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
)),
|
||||
),
|
||||
];
|
||||
let keyed_accounts: Vec<_> = accounts
|
||||
.iter()
|
||||
.map(|(key, account)| solana_sdk::keyed_account::KeyedAccount::new(&key, false, &account))
|
||||
.collect();
|
||||
let mut invoke_context = MockInvokeContext::new(&program_id, keyed_accounts);
|
||||
|
||||
let elf = load_elf("bench_alu").unwrap();
|
||||
let mut executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||
&elf,
|
||||
None,
|
||||
Config::default(),
|
||||
register_syscalls(&mut invoke_context).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
executable.jit_compile().unwrap();
|
||||
let compute_meter = invoke_context.get_compute_meter();
|
||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||
let mut vm = create_vm(
|
||||
&loader_id,
|
||||
executable.as_ref(),
|
||||
&mut inner_iter,
|
||||
&mut invoke_context,
|
||||
&[],
|
||||
)
|
||||
.unwrap();
|
||||
let loader_id = bpf_loader::id();
|
||||
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||
let mut executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||
&elf,
|
||||
None,
|
||||
Config::default(),
|
||||
register_syscalls(invoke_context).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
executable.jit_compile().unwrap();
|
||||
let compute_meter = invoke_context.get_compute_meter();
|
||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||
let mut vm = create_vm(
|
||||
&loader_id,
|
||||
executable.as_ref(),
|
||||
&mut inner_iter,
|
||||
invoke_context,
|
||||
&[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
println!("Interpreted:");
|
||||
assert_eq!(
|
||||
SUCCESS,
|
||||
vm.execute_program_interpreted(&mut instruction_meter)
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
|
||||
assert_eq!(
|
||||
ARMSTRONG_EXPECTED,
|
||||
LittleEndian::read_u64(&inner_iter[mem::size_of::<u64>()..])
|
||||
);
|
||||
println!("Interpreted:");
|
||||
assert_eq!(
|
||||
SUCCESS,
|
||||
vm.execute_program_interpreted(&mut instruction_meter)
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
|
||||
assert_eq!(
|
||||
ARMSTRONG_EXPECTED,
|
||||
LittleEndian::read_u64(&inner_iter[mem::size_of::<u64>()..])
|
||||
);
|
||||
|
||||
bencher.iter(|| {
|
||||
vm.execute_program_interpreted(&mut instruction_meter)
|
||||
.unwrap();
|
||||
bencher.iter(|| {
|
||||
vm.execute_program_interpreted(&mut instruction_meter)
|
||||
.unwrap();
|
||||
});
|
||||
let instructions = vm.get_total_instruction_count();
|
||||
let summary = bencher.bench(|_bencher| {}).unwrap();
|
||||
println!(" {:?} instructions", instructions);
|
||||
println!(" {:?} ns/iter median", summary.median as u64);
|
||||
assert!(0f64 != summary.median);
|
||||
let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million;
|
||||
println!(" {:?} MIPS", mips);
|
||||
println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_interpreted_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips);
|
||||
|
||||
println!("JIT to native:");
|
||||
assert_eq!(
|
||||
SUCCESS,
|
||||
vm.execute_program_jit(&mut instruction_meter).unwrap()
|
||||
);
|
||||
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
|
||||
assert_eq!(
|
||||
ARMSTRONG_EXPECTED,
|
||||
LittleEndian::read_u64(&inner_iter[mem::size_of::<u64>()..])
|
||||
);
|
||||
|
||||
bencher.iter(|| vm.execute_program_jit(&mut instruction_meter).unwrap());
|
||||
let summary = bencher.bench(|_bencher| {}).unwrap();
|
||||
println!(" {:?} instructions", instructions);
|
||||
println!(" {:?} ns/iter median", summary.median as u64);
|
||||
assert!(0f64 != summary.median);
|
||||
let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million;
|
||||
println!(" {:?} MIPS", mips);
|
||||
println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_jit_to_native_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips);
|
||||
});
|
||||
let instructions = vm.get_total_instruction_count();
|
||||
let summary = bencher.bench(|_bencher| {}).unwrap();
|
||||
println!(" {:?} instructions", instructions);
|
||||
println!(" {:?} ns/iter median", summary.median as u64);
|
||||
assert!(0f64 != summary.median);
|
||||
let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million;
|
||||
println!(" {:?} MIPS", mips);
|
||||
println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_interpreted_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips);
|
||||
|
||||
println!("JIT to native:");
|
||||
assert_eq!(
|
||||
SUCCESS,
|
||||
vm.execute_program_jit(&mut instruction_meter).unwrap()
|
||||
);
|
||||
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
|
||||
assert_eq!(
|
||||
ARMSTRONG_EXPECTED,
|
||||
LittleEndian::read_u64(&inner_iter[mem::size_of::<u64>()..])
|
||||
);
|
||||
|
||||
bencher.iter(|| vm.execute_program_jit(&mut instruction_meter).unwrap());
|
||||
let summary = bencher.bench(|_bencher| {}).unwrap();
|
||||
println!(" {:?} instructions", instructions);
|
||||
println!(" {:?} ns/iter median", summary.median as u64);
|
||||
assert!(0f64 != summary.median);
|
||||
let mips = (instructions * (ns_per_s / summary.median as u64)) / one_million;
|
||||
println!(" {:?} MIPS", mips);
|
||||
println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_jit_to_native_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
@@ -220,125 +200,102 @@ fn bench_program_execute_noop(bencher: &mut Bencher) {
|
||||
|
||||
#[bench]
|
||||
fn bench_create_vm(bencher: &mut Bencher) {
|
||||
const BUDGET: u64 = 200_000;
|
||||
let loader_id = bpf_loader::id();
|
||||
|
||||
let accounts = [RefCell::new(AccountSharedData::new(
|
||||
1,
|
||||
10000001,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
))];
|
||||
let keys = [solana_sdk::pubkey::new_rand()];
|
||||
let keyed_accounts: Vec<_> = keys
|
||||
.iter()
|
||||
.zip(&accounts)
|
||||
.map(|(key, account)| solana_sdk::keyed_account::KeyedAccount::new(&key, false, &account))
|
||||
.collect();
|
||||
let instruction_data = vec![0u8];
|
||||
|
||||
let mut invoke_context = MockInvokeContext::new(&loader_id, keyed_accounts);
|
||||
invoke_context.compute_meter = Rc::new(RefCell::new(MockComputeMeter { remaining: BUDGET }));
|
||||
|
||||
// Serialize account data
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||
let (mut serialized, account_lengths) = serialize_parameters(
|
||||
&loader_id,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
keyed_accounts,
|
||||
&instruction_data,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let elf = load_elf("noop").unwrap();
|
||||
let executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||
&elf,
|
||||
None,
|
||||
Config::default(),
|
||||
register_syscalls(&mut invoke_context).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let loader_id = bpf_loader::id();
|
||||
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||
const BUDGET: u64 = 200_000;
|
||||
let compute_meter = invoke_context.get_compute_meter();
|
||||
{
|
||||
let mut compute_meter = compute_meter.borrow_mut();
|
||||
let to_consume = compute_meter.get_remaining() - BUDGET;
|
||||
compute_meter.consume(to_consume).unwrap();
|
||||
}
|
||||
|
||||
bencher.iter(|| {
|
||||
let _ = create_vm(
|
||||
&loader_id,
|
||||
executable.as_ref(),
|
||||
serialized.as_slice_mut(),
|
||||
&mut invoke_context,
|
||||
&account_lengths,
|
||||
// Serialize account data
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||
let (mut serialized, account_lengths) = serialize_parameters(
|
||||
&keyed_accounts[0].unsigned_key(),
|
||||
&keyed_accounts[1].unsigned_key(),
|
||||
&keyed_accounts[2..],
|
||||
&[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||
&elf,
|
||||
None,
|
||||
Config::default(),
|
||||
register_syscalls(invoke_context).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
bencher.iter(|| {
|
||||
let _ = create_vm(
|
||||
&loader_id,
|
||||
executable.as_ref(),
|
||||
serialized.as_slice_mut(),
|
||||
invoke_context,
|
||||
&account_lengths,
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
||||
const BUDGET: u64 = 200_000;
|
||||
let loader_id = bpf_loader::id();
|
||||
let program_id = solana_sdk::pubkey::new_rand();
|
||||
|
||||
let accounts = [
|
||||
(
|
||||
program_id,
|
||||
RefCell::new(AccountSharedData::new(0, 0, &loader_id)),
|
||||
),
|
||||
(
|
||||
solana_sdk::pubkey::new_rand(),
|
||||
RefCell::new(AccountSharedData::new(
|
||||
1,
|
||||
10000001,
|
||||
&solana_sdk::pubkey::new_rand(),
|
||||
)),
|
||||
),
|
||||
];
|
||||
let keyed_accounts: Vec<_> = accounts
|
||||
.iter()
|
||||
.map(|(key, account)| solana_sdk::keyed_account::KeyedAccount::new(&key, false, &account))
|
||||
.collect();
|
||||
let instruction_data = vec![0u8];
|
||||
let mut invoke_context = MockInvokeContext::new(&program_id, keyed_accounts);
|
||||
invoke_context.compute_meter = Rc::new(RefCell::new(MockComputeMeter { remaining: BUDGET }));
|
||||
|
||||
// Serialize account data
|
||||
let (mut serialized, account_lengths) = serialize_parameters(
|
||||
&loader_id,
|
||||
&program_id,
|
||||
&invoke_context.get_keyed_accounts().unwrap()[1..],
|
||||
&instruction_data,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let elf = load_elf("tuner").unwrap();
|
||||
let executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||
&elf,
|
||||
None,
|
||||
Config::default(),
|
||||
register_syscalls(&mut invoke_context).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let compute_meter = invoke_context.get_compute_meter();
|
||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||
let mut vm = create_vm(
|
||||
&loader_id,
|
||||
executable.as_ref(),
|
||||
serialized.as_slice_mut(),
|
||||
&mut invoke_context,
|
||||
&account_lengths,
|
||||
)
|
||||
.unwrap();
|
||||
let loader_id = bpf_loader::id();
|
||||
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||
const BUDGET: u64 = 200_000;
|
||||
let compute_meter = invoke_context.get_compute_meter();
|
||||
{
|
||||
let mut compute_meter = compute_meter.borrow_mut();
|
||||
let to_consume = compute_meter.get_remaining() - BUDGET;
|
||||
compute_meter.consume(to_consume).unwrap();
|
||||
}
|
||||
|
||||
let mut measure = Measure::start("tune");
|
||||
let _ = vm.execute_program_interpreted(&mut instruction_meter);
|
||||
measure.stop();
|
||||
// Serialize account data
|
||||
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||
let (mut serialized, account_lengths) = serialize_parameters(
|
||||
&keyed_accounts[0].unsigned_key(),
|
||||
&keyed_accounts[1].unsigned_key(),
|
||||
&keyed_accounts[2..],
|
||||
&[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
0,
|
||||
instruction_meter.get_remaining(),
|
||||
"Tuner must consume the whole budget"
|
||||
);
|
||||
println!(
|
||||
"{:?} compute units took {:?} us ({:?} instructions)",
|
||||
BUDGET - instruction_meter.get_remaining(),
|
||||
measure.as_us(),
|
||||
vm.get_total_instruction_count(),
|
||||
);
|
||||
let executable = <dyn Executable<BpfError, ThisInstructionMeter>>::from_elf(
|
||||
&elf,
|
||||
None,
|
||||
Config::default(),
|
||||
register_syscalls(invoke_context).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||
let mut vm = create_vm(
|
||||
&loader_id,
|
||||
executable.as_ref(),
|
||||
serialized.as_slice_mut(),
|
||||
invoke_context,
|
||||
&account_lengths,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut measure = Measure::start("tune");
|
||||
let _ = vm.execute_program_interpreted(&mut instruction_meter);
|
||||
measure.stop();
|
||||
|
||||
assert_eq!(
|
||||
0,
|
||||
instruction_meter.get_remaining(),
|
||||
"Tuner must consume the whole budget"
|
||||
);
|
||||
println!(
|
||||
"{:?} compute units took {:?} us ({:?} instructions)",
|
||||
BUDGET - instruction_meter.get_remaining(),
|
||||
measure.as_us(),
|
||||
vm.get_total_instruction_count(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user