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

chilli pepper(wip) #4372

Draft
wants to merge 29 commits into
base: master
Choose a base branch
from
10 changes: 10 additions & 0 deletions Cargo.lock

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

8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,10 @@ index_list = "0.2.15"
indexmap = "2.7.0"
indicatif = "0.17.9"
itertools = "0.12.1"
jemallocator = { package = "tikv-jemallocator", version = "0.6.0", features = [
"unprefixed_malloc_on_supported_platforms",
] }
#jemallocator = { package = "tikv-jemallocator", version = "0.6.0", features = [
# "unprefixed_malloc_on_supported_platforms",
#] }
jemallocator = { package = "tikv-jemallocator", version = "0.6.0", features = ["profiling", "unprefixed_malloc_on_supported_platforms"] }
js-sys = "0.3.76"
json5 = "0.4.1"
jsonrpc-core = "18.0.0"
Expand Down Expand Up @@ -409,6 +410,7 @@ rand0-7 = { package = "rand", version = "0.7" }
rand_chacha = "0.3.1"
rand_chacha0-2 = { package = "rand_chacha", version = "0.2.2" }
rayon = "1.10.0"
redb = "2.2.0"
reed-solomon-erasure = "6.0.0"
regex = "1.11.1"
reqwest = { version = "0.11.27", default-features = false }
Expand Down
5 changes: 5 additions & 0 deletions accounts-db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ num_enum = { workspace = true }
qualifier_attr = { workspace = true, optional = true }
rand = { workspace = true }
rayon = { workspace = true }
redb = { workspace = true }
seqlock = { workspace = true }
serde = { workspace = true, features = ["rc"] }
serde_derive = { workspace = true }
Expand Down Expand Up @@ -119,5 +120,9 @@ harness = false
name = "bench_lock_accounts"
harness = false

[[bench]]
name = "bench_chili_pepper_store"
harness = false

[lints]
workspace = true
59 changes: 59 additions & 0 deletions accounts-db/benches/bench_chili_pepper_store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/// Benchmarks for the `ChiliPepperStore` implementation.
/// pass benchmark_group name in the command line to run a specific benchmark group.
/// > ../cargo nightly bench -- chili_pepper_store
use {
criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput},
solana_accounts_db::chili_pepper::chili_pepper_store::{ChiliPepperStoreWrapper, PubkeySlot},
solana_sdk::pubkey::Pubkey,
std::env::current_dir,
tempfile::NamedTempFile,
};

const ELEMENTS: [u64; 6] = [1_000, 10_000, 100_000, 200_000, 500_000, 1_000_000]; // 1K, 10K, 100K, 1M

fn bench_chili_pepper_store(c: &mut Criterion) {
let tmpfile: NamedTempFile = NamedTempFile::new_in(current_dir().unwrap()).unwrap();
let store = ChiliPepperStoreWrapper::new_with_path(tmpfile.path()).unwrap();

let mut group = c.benchmark_group("chili_pepper_store");
group.significance_level(0.1).sample_size(10);

for size in ELEMENTS {
group.throughput(Throughput::Elements(size as u64));

let mut pubkeys = vec![];
for _ in 0..size {
pubkeys.push(Pubkey::new_unique());
}

let data = pubkeys
.iter()
.map(|k| (PubkeySlot::new(k, 42), 163))
.collect::<Vec<_>>();

group.bench_function(BenchmarkId::new("insert", size), |b| {
b.iter(|| {
store.bulk_insert(data.iter().copied()).unwrap();
});
});

group.bench_function(BenchmarkId::new("get", size), |b| {
b.iter(|| {
for (key, value) in data.iter() {
let result = store.get(*key).unwrap();
assert_eq!(result, Some(*value));
}
});
});

group.bench_function(BenchmarkId::new("bulk_get", size), |b| {
b.iter(|| {
let v = store.bulk_get_for_pubkeys(&pubkeys).unwrap();
assert_eq!(v.len(), size as usize);
});
});
}
}

criterion_group!(benches, bench_chili_pepper_store);
criterion_main!(benches);
108 changes: 108 additions & 0 deletions accounts-db/doc/chili_pepper_meeting_2024_11_20.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Chili Pepper Meeting Notes (2024/11/20)

This document is written to help us to define the architecture design for the
chili pepper feature. The following section describes the new components
required, new system parameters and new behavior changes.

## New Components

### Chili Pepper Store

We will implement a new store to store chili pepper meters per account. See
`chili pepper store desgin` for more details

### New sysvar

A per block sysvar to store the chili pepper clock per block.

```rust
struct SysvarBlockChiliPepperClock {
chili_pepper_clock : u64;
}
```

### New ComputeBudgetInstruction

A new instruction to specify the chili pepper limit per transaction.

```rust
ComputeBudgetInstruction::SetChiliPepperLimit(u32)
```

## New system Parameters

### Block chili pepper limit

Specify the maximum number of chili peppers that a block can consume. One chili
pepper is one byte.

This number can be derived from the disk (SSD) -> memory bandwidth.
- Do we assume that it is one SSD or multiple SSDs?
- Which generation SSD specs should we use for bandwidth?

### Hot cache size

Represents the number of bytes, which are used by the current bank to offset
current chili pepper clock to determine whether and account is hot or cold.

However, there are two concerns to use the hot cache memory directly.

- "hot cache size" is global and shared between all the forks, while the
current chili pepper clock is per fork. It only tracks the number of chili
pepper on current fork. When in fork, the byte for `account's byte in cache
will be less than the hot cache size`.

- the hot cache size is not only used for cache accounts' data. It is also used for
storing the account's meta in account's index and account's chili pepper.

So probably, we will budget it to a smaller percentage of the total memory
commit to "hot cache". What percentage?


## Replayer side changes

With chili pepper, we will need to change the work flow for replay. The new
imagined flow will be follows.

```
input: block of tx

fn replay(block) -> Result<>

total_chili_pepper_requested = sum(tx.requested_chili_pepper for all tx);

if total_chili_pepper > block_chili_pepper_limit:
fail the block

threshold = chili_pepper_sysvar.read() + total_chili_pepper - hot_cache_size;
chili_pepper_syavar.update(chili_pepper_in_sysvar + total_chili_pepper);

used_chili_pepper = 0
foreach tx:
foreach account in tx:
used_chili_pepper += account.last_chili_pepper < threshold ? account.size : 0;
if used_chili_pepper > tx.requested_chili_peper:
fail the tx
execute(tx);
for each account in tx:
commit_chili_pepper(account, chili_pepper_sysavar.read());
```

## Leader side changes

Given a set of txs, the banking stage need to change to make sure that the block
it packed doesn't exceeds the block level chili pepper limits.

## Dapp program Changes

Dapp transaction may need to include the instruction to set chili_pepper limit.

## Handling deleted accounts

> An account that is deleted is still considered hot until its state unit clock
> lapses into cold. Creating an account against a deleted account which is still
> hot, will create the hot account again.

This implies a change for our account's db (i.e. clean, shrink, snapshot). We
will need to keep track of all deleted accounts, while is still hot in the
cache. This can increase the accounts index, storage and snapshot size?
Loading
Loading