Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 666dae0

Browse files
committed
programs/sbf: bench running programs with input accounts
1 parent 35427ee commit 666dae0

File tree

7 files changed

+386
-0
lines changed

7 files changed

+386
-0
lines changed

programs/sbf/Cargo.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

programs/sbf/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ solana-program-runtime = { path = "../../program-runtime", version = "=1.16.0" }
3737
solana-program-test = { path = "../../program-test", version = "=1.16.0" }
3838
solana-runtime = { path = "../../runtime", version = "=1.16.0" }
3939
solana-sbf-rust-128bit-dep = { path = "rust/128bit_dep", version = "=1.16.0" }
40+
solana-sbf-rust-bench = { path = "rust/bench", version = "=1.16.0" }
4041
solana-sbf-rust-invoke = { path = "rust/invoke", version = "=1.16.0" }
4142
solana-sbf-rust-invoked = { path = "rust/invoked", version = "=1.16.0", default-features = false }
4243
solana-sbf-rust-many-args-dep = { path = "rust/many_args_dep", version = "=1.16.0" }
@@ -85,6 +86,7 @@ solana-logger = { workspace = true }
8586
solana-measure = { workspace = true }
8687
solana-program-runtime = { workspace = true }
8788
solana-runtime = { workspace = true }
89+
solana-sbf-rust-bench = { workspace = true }
8890
solana-sbf-rust-invoke = { workspace = true }
8991
solana-sbf-rust-realloc = { workspace = true, features = ["default"] }
9092
solana-sbf-rust-realloc-invoke = { workspace = true }
@@ -104,6 +106,7 @@ members = [
104106
"rust/128bit_dep",
105107
"rust/alloc",
106108
"rust/alt_bn128",
109+
"rust/bench",
107110
"rust/big_mod_exp",
108111
"rust/call_depth",
109112
"rust/caller_access",
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#![feature(test)]
2+
#![cfg(feature = "sbf_rust")]
3+
4+
use solana_sbf_rust_bench::instructions::Recurse;
5+
6+
extern crate test;
7+
8+
use {
9+
solana_bpf_loader_program::solana_bpf_loader_program,
10+
solana_runtime::{
11+
bank::Bank,
12+
bank_client::BankClient,
13+
genesis_utils::{create_genesis_config, GenesisConfigInfo},
14+
loader_utils::load_program,
15+
},
16+
solana_sbf_rust_bench::instructions::{BenchInstruction, ReadAccounts, WriteAccounts},
17+
solana_sdk::{
18+
account::AccountSharedData,
19+
bpf_loader,
20+
client::SyncClient,
21+
instruction::{AccountMeta, Instruction},
22+
message::Message,
23+
pubkey::Pubkey,
24+
signature::Signer,
25+
},
26+
std::sync::Arc,
27+
test::Bencher,
28+
};
29+
30+
fn bench_accounts(
31+
bencher: &mut Bencher,
32+
num_accounts: usize,
33+
account_size: usize,
34+
instruction: BenchInstruction,
35+
) {
36+
solana_logger::setup();
37+
38+
let GenesisConfigInfo {
39+
genesis_config,
40+
mint_keypair,
41+
..
42+
} = create_genesis_config(50);
43+
let mut bank = Bank::new_for_benches(&genesis_config);
44+
let (name, id, entrypoint) = solana_bpf_loader_program!();
45+
bank.add_builtin(&name, &id, entrypoint);
46+
let bank = Arc::new(bank);
47+
let bank_client = BankClient::new_shared(&bank);
48+
49+
let program_id = load_program(
50+
&bank_client,
51+
&bpf_loader::id(),
52+
&mint_keypair,
53+
"solana_sbf_rust_bench",
54+
);
55+
56+
let accounts = (0..num_accounts)
57+
.map(|_| {
58+
(
59+
Pubkey::new_unique(),
60+
AccountSharedData::new(10, account_size, &program_id),
61+
)
62+
})
63+
.collect::<Vec<_>>();
64+
65+
for (pubkey, account) in &accounts {
66+
bank.store_account(pubkey, account);
67+
}
68+
69+
let mint_pubkey = mint_keypair.pubkey();
70+
let mut account_metas = accounts
71+
.iter()
72+
.map(|(pubkey, _)| AccountMeta::new(*pubkey, false))
73+
.collect::<Vec<_>>();
74+
account_metas.push(AccountMeta::new(program_id, false));
75+
76+
let instruction = Instruction {
77+
program_id,
78+
accounts: account_metas,
79+
data: instruction.to_bytes(),
80+
};
81+
let message = Message::new(&[instruction], Some(&mint_pubkey));
82+
83+
bank_client
84+
.send_and_confirm_message(&[&mint_keypair], message.clone())
85+
.unwrap();
86+
87+
bencher.iter(|| {
88+
bank.clear_signatures();
89+
bank_client
90+
.send_and_confirm_message(&[&mint_keypair], message.clone())
91+
.unwrap();
92+
});
93+
}
94+
95+
macro_rules! bench_program_execute_read_accounts {
96+
($($name:ident: $num_accounts:expr, $account_size:expr, $read_size:expr),+) => {
97+
$(
98+
#[bench]
99+
fn $name(bencher: &mut Bencher) {
100+
bench_accounts(bencher, $num_accounts, $account_size, BenchInstruction::ReadAccounts(ReadAccounts {
101+
num_accounts: $num_accounts,
102+
size: $read_size,
103+
}))
104+
}
105+
)+
106+
};
107+
}
108+
109+
bench_program_execute_read_accounts!(
110+
bench_program_execute_read_1_1k_account: 1, 1024, 1,
111+
bench_program_execute_read_1_100k_account: 1, 100 * 1024, 1,
112+
bench_program_execute_read_1_1mb_account: 1, 1024 * 1024, 1,
113+
bench_program_execute_read_1_10mb_account: 1, 10 * 1024 * 1024, 1,
114+
115+
bench_program_execute_read_10_1k_account: 10, 1024, 1,
116+
bench_program_execute_read_10_100k_account: 10, 100 * 1024, 1,
117+
bench_program_execute_read_10_1mb_account: 10, 1024 * 1024, 1,
118+
119+
bench_program_execute_read_126_1k_account: 126, 1024, 1,
120+
bench_program_execute_read_126_100k_account: 126, 100 * 1024, 1,
121+
bench_program_execute_read_126_500k_account: 126, 500 * 1024, 1
122+
);
123+
124+
macro_rules! bench_program_execute_write_accounts {
125+
($($name:ident: $num_accounts:expr, $account_size:expr, $write_size:expr),+) => {
126+
$(
127+
#[bench]
128+
fn $name(bencher: &mut Bencher) {
129+
bench_accounts(bencher, $num_accounts, $account_size, BenchInstruction::WriteAccounts(WriteAccounts {
130+
num_accounts: 1,
131+
size: $write_size,
132+
}))
133+
}
134+
)+
135+
};
136+
}
137+
138+
bench_program_execute_write_accounts!(
139+
bench_program_execute_write_1_1k_account: 1, 1024, 1,
140+
bench_program_execute_write_1_100k_account: 1, 100 * 1024, 1,
141+
bench_program_execute_write_1_1mb_account: 1, 1024 * 1024, 1,
142+
bench_program_execute_write_1_10mb_account: 1, 10 * 1024 * 1024, 1,
143+
144+
bench_program_execute_write_10_1k_account: 10, 1024, 1,
145+
bench_program_execute_write_10_100k_account: 10, 100 * 1024, 1,
146+
bench_program_execute_write_10_1mb_account: 10, 1024 * 1024, 1,
147+
148+
bench_program_execute_write_126_1k_account: 126, 1024, 1,
149+
bench_program_execute_write_126_100k_account: 126, 100 * 1024, 1,
150+
bench_program_execute_write_126_500k_account: 126, 500 * 1024, 1
151+
);
152+
macro_rules! bench_program_execute_recurse {
153+
($($name:ident: $num_accounts:expr, $account_size:expr, $n:expr),+) => {
154+
$(
155+
#[bench]
156+
fn $name(bencher: &mut Bencher) {
157+
bench_accounts(bencher, $num_accounts, $account_size, BenchInstruction::Recurse(Recurse {
158+
n: $n
159+
}))
160+
}
161+
)+
162+
};
163+
}
164+
165+
bench_program_execute_recurse!(
166+
bench_program_execute_recurse_1_1k_account: 1, 1024, 4,
167+
bench_program_execute_recurse_1_100k_account: 1, 100 * 1024, 4,
168+
bench_program_execute_recurse_1_1mb_account: 1, 1024 * 1024, 4,
169+
bench_program_execute_recurse_1_10mb_account: 1, 10 * 1024 * 1024, 4,
170+
171+
bench_program_execute_recurse_10_1k_account: 10, 1024, 4,
172+
bench_program_execute_recurse_10_100k_account: 10, 100 * 1024, 4,
173+
174+
bench_program_execute_recurse_50_1k_account: 50, 1024, 1,
175+
bench_program_execute_recurse_50_100k_account: 50, 100 * 1024, 1
176+
);

programs/sbf/rust/bench/Cargo.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[package]
2+
name = "solana-sbf-rust-bench"
3+
documentation = "https://docs.rs/solana-sbf-rust-bench"
4+
version = { workspace = true }
5+
description = { workspace = true }
6+
authors = { workspace = true }
7+
repository = { workspace = true }
8+
homepage = { workspace = true }
9+
license = { workspace = true }
10+
edition = { workspace = true }
11+
12+
[features]
13+
default = ["program"]
14+
program = []
15+
16+
[dependencies]
17+
solana-program = { workspace = true }
18+
19+
[lib]
20+
crate-type = ["lib", "cdylib"]
21+
22+
[package.metadata.docs.rs]
23+
targets = ["x86_64-unknown-linux-gnu"]
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//! Example Rust-based SBF program that issues a cross-program-invocation
2+
3+
use {
4+
core::slice,
5+
std::{mem, ptr},
6+
};
7+
8+
pub enum BenchInstruction {
9+
Nop,
10+
ReadAccounts(ReadAccounts),
11+
WriteAccounts(WriteAccounts),
12+
Recurse(Recurse),
13+
}
14+
15+
impl BenchInstruction {
16+
pub fn tag(&self) -> u8 {
17+
match self {
18+
BenchInstruction::Nop => 0,
19+
BenchInstruction::ReadAccounts(_) => 1,
20+
BenchInstruction::WriteAccounts(_) => 2,
21+
BenchInstruction::Recurse(_) => 3,
22+
}
23+
}
24+
25+
pub fn to_bytes(&self) -> Vec<u8> {
26+
let mut bytes = vec![self.tag()];
27+
match self {
28+
BenchInstruction::Nop => {}
29+
BenchInstruction::ReadAccounts(read_accounts) => bytes.extend_from_slice(unsafe {
30+
slice::from_raw_parts(
31+
read_accounts as *const _ as *const u8,
32+
mem::size_of::<ReadAccounts>(),
33+
)
34+
}),
35+
BenchInstruction::WriteAccounts(write_accounts) => bytes.extend_from_slice(unsafe {
36+
slice::from_raw_parts(
37+
write_accounts as *const _ as *const u8,
38+
mem::size_of::<WriteAccounts>(),
39+
)
40+
}),
41+
BenchInstruction::Recurse(recurse) => bytes.extend_from_slice(unsafe {
42+
slice::from_raw_parts(recurse as *const _ as *const u8, mem::size_of::<Recurse>())
43+
}),
44+
}
45+
bytes
46+
}
47+
}
48+
49+
impl TryFrom<&[u8]> for BenchInstruction {
50+
type Error = ();
51+
52+
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
53+
let (tag, rest) = input.split_first().ok_or(())?;
54+
match tag {
55+
0 => Ok(BenchInstruction::Nop),
56+
1 => {
57+
let read_accounts =
58+
unsafe { ptr::read_unaligned(rest.as_ptr() as *const ReadAccounts) };
59+
Ok(BenchInstruction::ReadAccounts(read_accounts))
60+
}
61+
2 => {
62+
let write_accounts =
63+
unsafe { ptr::read_unaligned(rest.as_ptr() as *const WriteAccounts) };
64+
Ok(BenchInstruction::WriteAccounts(write_accounts))
65+
}
66+
3 => {
67+
let recurse = unsafe { ptr::read_unaligned(rest.as_ptr() as *const Recurse) };
68+
Ok(BenchInstruction::Recurse(recurse))
69+
}
70+
_ => Err(()),
71+
}
72+
}
73+
}
74+
75+
#[repr(C)]
76+
pub struct ReadAccounts {
77+
pub num_accounts: usize,
78+
pub size: usize,
79+
}
80+
81+
#[repr(C)]
82+
pub struct WriteAccounts {
83+
pub num_accounts: usize,
84+
pub size: usize,
85+
}
86+
87+
#[repr(C)]
88+
pub struct Recurse {
89+
pub n: usize,
90+
}

programs/sbf/rust/bench/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//! Example Rust-based SBF program that issues a cross-program-invocation
2+
3+
pub mod instructions;
4+
pub mod processor;

0 commit comments

Comments
 (0)