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

Only keep track of recently used stacks in memory. #2591

Open
wants to merge 33 commits into
base: staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
44fc174
Only keep track of recently used stacks in memory.
vicsn Jan 10, 2025
9486378
Revert MAX_TRANSMISSIONS_PER_BATCH location
vicsn Jan 10, 2025
9e56e07
Fix circleci resource
vicsn Jan 10, 2025
4a93690
Lower MAX_STACKS when testing
vicsn Jan 11, 2025
135e279
Resolve bugs
vicsn Jan 11, 2025
e76606d
Fix tests: don't superfluously cache credits.aleo
vicsn Jan 13, 2025
678fa94
Update circleci config
vicsn Jan 13, 2025
ce57e74
Update MAX_STACKS to fix test_long_import_chain
vicsn Jan 13, 2025
9e19924
Update ledger/narwhal/batch-header/src/lib.rs
vicsn Jan 14, 2025
8bf0d8d
Update synthesizer/process/src/lib.rs
vicsn Jan 14, 2025
b884134
Update synthesizer/process/src/lib.rs
vicsn Jan 14, 2025
ed2d269
Update synthesizer/process/src/lib.rs
vicsn Jan 14, 2025
f9eaab6
Update synthesizer/process/src/lib.rs
vicsn Jan 14, 2025
fc0ec5f
Get rid of stacks contention
vicsn Jan 15, 2025
3291ccc
Correct typedef name
vicsn Jan 20, 2025
12345aa
Fix slow test; might need DB fix to pass
vicsn Jan 20, 2025
b1e2a0a
Reduce size of feature gating diff
vicsn Jan 20, 2025
f1022e3
Only use num_stacks_in_memory in tests
vicsn Jan 20, 2025
a16db98
Cargo fmt
vicsn Jan 20, 2025
2dc6770
Remove useless logs
vicsn Jan 20, 2025
f3fb877
Remove clone
vicsn Jan 20, 2025
67ac36b
Howard's spirit lives on
vicsn Jan 20, 2025
f812a4b
Keep it DRY
vicsn Jan 20, 2025
9b61b78
contains_program_in_memory -> contains_program_in_cache
vicsn Jan 20, 2025
d3ab602
Improve logging
vicsn Jan 20, 2025
8b1a28a
Speed up credits.aleo comparison
vicsn Jan 20, 2025
c630a36
remove incorrect comment
vicsn Jan 20, 2025
c5fc425
Merge remote-tracking branch 'provable/staging' into stack_cache_relo…
vicsn Jan 20, 2025
0bddecd
Try to avoid OOM
vicsn Jan 20, 2025
f2bf9fe
Fix test_long_import_chain
vicsn Jan 20, 2025
aac3fd0
Fix circleci
vicsn Jan 20, 2025
2e8c41c
Fix real evict example
vicsn Jan 20, 2025
815eecd
Try to avoid computing credits.aleo program id
vicsn Jan 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ jobs:
ledger-with-rocksdb:
docker:
- image: cimg/rust:1.81.0 # Attention - Change the MSRV in Cargo.toml and rust-toolchain as well
resource_class: << pipeline.parameters.medium >>
resource_class: << pipeline.parameters.large >>
steps:
- run_serial:
flags: --features=rocks
Expand Down Expand Up @@ -692,7 +692,7 @@ jobs:
resource_class: << pipeline.parameters.twoxlarge >>
steps:
- run_serial:
flags: -- --ignored test_deployment_synthesis_overload test_deep_nested_execution_cost
flags: -- --ignored test_deployment_synthesis_overload test_deep_nested_execution_cost -- --test-threads=1
workspace_member: synthesizer
cache_key: v1.0.0-rust-1.81.0-snarkvm-synthesizer-mem-heavy-cache

Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions console/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ pub trait Network:
// Increasing this value will require a migration to prevent forking during network upgrades.
const MAX_CERTIFICATES: u16;

/// The maximum number of stacks in the process.
/// Must be at least Self::MAX_PROGRAM_DEPTH * Self::MAX_IMPORTS to be safe.
const MAX_STACKS: usize = Self::MAX_PROGRAM_DEPTH * Self::MAX_IMPORTS * 10;

/// The maximum number of bytes in a transaction.
// Note: This value must **not** be decreased as it would invalidate existing transactions.
const MAX_TRANSACTION_SIZE: usize = 128_000; // 128 kB
Expand Down
2 changes: 1 addition & 1 deletion ledger/block/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ pub mod test_helpers {
let inputs = [address.to_string(), format!("{amount}_u64")];

// Initialize the process.
let process = Process::load().unwrap();
let process = Process::load_testing_only().unwrap();
// Authorize the function.
let authorization =
process.authorize::<CurrentAleo, _>(&private_key, locator.0, locator.1, inputs.iter(), rng).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion ledger/block/src/transaction/deployment/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ function compute:
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");

// Construct the process.
let process = Process::load().unwrap();
let process = Process::load_testing_only().unwrap();
// Compute the deployment.
let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap();
// Return the deployment.
Expand Down
4 changes: 2 additions & 2 deletions ledger/block/src/transaction/fee/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ pub mod test_helpers {
let priority_fee_in_microcredits = 1_000;

// Initialize the process.
let process = Process::load().unwrap();
let process = Process::load_testing_only().unwrap();
// Authorize the fee.
let authorization = process
.authorize_fee_private::<CurrentAleo, _>(
Expand Down Expand Up @@ -298,7 +298,7 @@ pub mod test_helpers {
let priority_fee = 1_000;

// Initialize the process.
let process = Process::load().unwrap();
let process = Process::load_testing_only().unwrap();
// Authorize the fee.
let authorization = process
.authorize_fee_public::<CurrentAleo, _>(
Expand Down
2 changes: 1 addition & 1 deletion ledger/narwhal/batch-header/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl<N: Network> BatchHeader<N> {
pub const MAX_CERTIFICATES_BEFORE_V3: u16 = 100;
/// The maximum number of rounds to store before garbage collecting.
pub const MAX_GC_ROUNDS: usize = 100;
/// The maximum number of transmissions in a batch.
/// The maximum number of transmissions per batch.
/// Note: This limit is set to 50 as part of safety measures to prevent DoS attacks.
/// This limit can be increased in the future as performance improves. Alternatively,
/// the rate of block production can be sped up to compensate for the limit set here.
Expand Down
2 changes: 1 addition & 1 deletion ledger/puzzle/epoch/src/synthesis/program/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function synthesize:
let program = Program::from_str(&program_string)?;

// Initialize a new process.
let process = Process::<N>::load()?;
let process = Process::<N>::load_no_storage()?;
// Initialize the stack with the synthesis challenge program.
let stack = Stack::new(&process, &program)?;

Expand Down
4 changes: 2 additions & 2 deletions ledger/query/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl<N: Network, B: BlockStorage<N>> QueryTrait<N> for Query<N, B> {
}
}

/// Returns a state path for the given `commitment`.
/// Returns the current block height.
fn current_block_height(&self) -> Result<u32> {
match self {
Self::VM(block_store) => Ok(block_store.max_height().unwrap_or_default()),
Expand All @@ -159,7 +159,7 @@ impl<N: Network, B: BlockStorage<N>> QueryTrait<N> for Query<N, B> {
}
}

/// Returns a state path for the given `commitment`.
/// Returns the current block height.
#[cfg(feature = "async")]
async fn current_block_height_async(&self) -> Result<u32> {
match self {
Expand Down
10 changes: 5 additions & 5 deletions ledger/test-helpers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ function compute:
assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");

// Construct the process.
let process = Process::load().unwrap();
let process = Process::load_testing_only().unwrap();
// Compute the deployment.
let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap();
// Return the deployment.
Expand Down Expand Up @@ -230,7 +230,7 @@ pub fn sample_fee_private(deployment_or_execution_id: Field<CurrentNetwork>, rng
let priority_fee_in_microcredits = 1_000;

// Initialize the process.
let process = Process::load().unwrap();
let process = Process::load_testing_only().unwrap();
// Authorize the fee.
let authorization = process
.authorize_fee_private::<CurrentAleo, _>(
Expand Down Expand Up @@ -284,7 +284,7 @@ pub fn sample_fee_public(deployment_or_execution_id: Field<CurrentNetwork>, rng:
let priority_fee_in_microcredits = 1_000;

// Initialize the process.
let process = Process::load().unwrap();
let process = Process::load_testing_only().unwrap();
// Authorize the fee.
let authorization = process
.authorize_fee_public::<CurrentAleo, _>(
Expand Down Expand Up @@ -399,7 +399,7 @@ pub fn sample_large_execution_transaction(rng: &mut TestRng) -> Transaction<Curr
let program = large_transaction_program();

// Construct the process.
let mut process = synthesizer_process::Process::load().unwrap();
let mut process = synthesizer_process::Process::load_testing_only().unwrap();
// Add the program.
process.add_program(&program).unwrap();

Expand Down Expand Up @@ -510,7 +510,7 @@ fn sample_genesis_block_and_components_raw(
let inputs = [address.to_string(), format!("{amount}_u64")];

// Initialize the process.
let process = Process::load().unwrap();
let process = Process::load_testing_only().unwrap();
// Authorize the function.
let authorization =
process.authorize::<CurrentAleo, _>(&private_key, locator.0, locator.1, inputs.iter(), rng).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion synthesizer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ aleo-cli = [ ]
async = [ "ledger-query/async", "synthesizer-process/async" ]
cuda = [ "algorithms/cuda" ]
history = [ "serde" ]
rocks = [ "ledger-store/rocks" ]
rocks = ["ledger-store/rocks", "synthesizer-process/rocks"]
serial = [
"console/serial",
"ledger-block/serial",
Expand Down
8 changes: 7 additions & 1 deletion synthesizer/process/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ version = "=1.2.1"

[dependencies.aleo-std]
version = "0.1.24"
default-features = false
features = ["storage"]

[dependencies.colored]
version = "2"
Expand All @@ -104,6 +104,9 @@ version = "2"
version = "2.0"
features = [ "serde" ]

[dependencies.lru]
version = "0.12"

[dependencies.once_cell]
version = "1.18"

Expand All @@ -124,6 +127,9 @@ optional = true
version = "1.0"
features = [ "preserve_order" ]

[dependencies.tracing]
version = "0.1"

[dev-dependencies.bincode]
version = "1.3"

Expand Down
4 changes: 2 additions & 2 deletions synthesizer/process/benches/stack_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn bench_stack_new(c: &mut Criterion) {
let mut rng = TestRng::default();

// Initialize a process.
let mut process = Process::load().unwrap();
let mut process = Process::load_testing_only().unwrap();

// Benchmark the base case.
c.bench_function("Depth 0 | Stack::new", |b| {
Expand Down Expand Up @@ -98,7 +98,7 @@ fn bench_stack_get_number_of_calls(c: &mut Criterion) {
const DEPTHS: [usize; 6] = [1, 2, 4, 8, 16, 30];

// Initialize a process.
let mut process = Process::load().unwrap();
let mut process = Process::load_testing_only().unwrap();

// Add the 0th program to the process.
add_program_at_depth(&mut process, 0);
Expand Down
4 changes: 2 additions & 2 deletions synthesizer/process/src/cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ pub fn execution_cost_v1<N: Network>(process: &Process<N>, execution: &Execution

// Get the finalize cost for the root transition.
let stack = process.get_stack(transition.program_id())?;
let finalize_cost = cost_in_microcredits_v1(stack, transition.function_name())?;
let finalize_cost = cost_in_microcredits_v1(&stack, transition.function_name())?;

// Compute the total cost in microcredits.
let total_cost = storage_cost
Expand Down Expand Up @@ -522,7 +522,7 @@ function over_five_thousand:
let threshold = MainnetV0::EXECUTION_STORAGE_PENALTY_THRESHOLD;

// Test the cost of an execution.
let mut process = Process::load().unwrap();
let mut process = Process::load_testing_only().unwrap();

// Get the program.
let program = Program::from_str(SIZE_BOUNDARY_PROGRAM).unwrap();
Expand Down
40 changes: 36 additions & 4 deletions synthesizer/process/src/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,39 @@ impl<N: Network> Process<N> {
deployment
}

/// Adds the newly-deployed program.
/// Loads the stack and imported stacks for the given program ID into memory.
#[inline]
pub fn load_stack(&self, program_id: impl TryInto<ProgramID<N>>) -> Result<Arc<Stack<N>>> {
let program_id = program_id.try_into().map_err(|_| anyhow!("Invalid program ID"))?;
debug!("Lazy loading stack for {program_id}");
// Retrieve the stores.
let store = self.store.as_ref().ok_or_else(|| anyhow!("Failed to get store"))?;
// Retrieve the transaction store.
let transaction_store = store.transaction_store();

// Retrieve the deployment store.
let deployment_store = transaction_store.deployment_store();
// Retrieve the transaction ID.
let transaction_id = deployment_store
.find_transaction_id_from_program_id(&program_id)
.map_err(|e| anyhow!("Program ID not found in storage: {e}"))?
.ok_or_else(|| anyhow!("Program ID not found in storage"))?;

// Retrieve the deployment from the transaction ID.
let deployment = match transaction_store.get_deployment(&transaction_id)? {
Some(deployment) => deployment,
None => bail!("Deployment transaction '{transaction_id}' is not found in storage."),
};

// Load the deployment into memory and return it.
// When initializing the corresponding Stack, each import Stack will be loaded recursively.
self.load_deployment(deployment)
}

/// Constructs, loads and returns the Stack from the deployment.
/// This method assumes the given deployment **is valid**.
#[inline]
pub fn load_deployment(&mut self, deployment: &Deployment<N>) -> Result<()> {
fn load_deployment(&self, deployment: Deployment<N>) -> Result<Arc<Stack<N>>> {
let timer = timer!("Process::load_deployment");

// Compute the program stack.
Expand All @@ -54,11 +83,14 @@ impl<N: Network> Process<N> {
}
lap!(timer, "Insert the verifying keys");

// Wrap the stack in an Arc.
let stack = Arc::new(stack);

// Add the stack to the process.
self.add_stack(stack);
self.add_stack(stack.clone())?;

finish!(timer);

Ok(())
Ok(stack)
}
}
4 changes: 2 additions & 2 deletions synthesizer/process/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ mod tests {
let rng = &mut TestRng::default();

// Initialize the process.
let process = Process::<CurrentNetwork>::load().unwrap();
let process = Process::<CurrentNetwork>::load_testing_only().unwrap();

// Sample a private key.
let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
Expand Down Expand Up @@ -124,7 +124,7 @@ mod tests {
let rng = &mut TestRng::default();

// Initialize the process.
let process = Process::<CurrentNetwork>::load().unwrap();
let process = Process::<CurrentNetwork>::load_testing_only().unwrap();

// Sample a private key.
let private_key = PrivateKey::new(rng).unwrap();
Expand Down
12 changes: 6 additions & 6 deletions synthesizer/process/src/finalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl<N: Network> Process<N> {
// Retrieve the fee stack.
let fee_stack = self.get_stack(fee.program_id())?;
// Finalize the fee transition.
finalize_operations.extend(finalize_fee_transition(state, store, fee_stack, fee)?);
finalize_operations.extend(finalize_fee_transition(state, store, &fee_stack, fee)?);
lap!(timer, "Finalize transition for '{}/{}'", fee.program_id(), fee.function_name());

/* Finalize the deployment. */
Expand Down Expand Up @@ -114,15 +114,15 @@ impl<N: Network> Process<N> {
// Finalize the root transition.
// Note that this will result in all the remaining transitions being finalized, since the number
// of calls matches the number of transitions.
let mut finalize_operations = finalize_transition(state, store, stack, transition, call_graph)?;
let mut finalize_operations = finalize_transition(state, store, &stack, transition, call_graph)?;

/* Finalize the fee. */

if let Some(fee) = fee {
// Retrieve the fee stack.
let fee_stack = self.get_stack(fee.program_id())?;
// Finalize the fee transition.
finalize_operations.extend(finalize_fee_transition(state, store, fee_stack, fee)?);
finalize_operations.extend(finalize_fee_transition(state, store, &fee_stack, fee)?);
lap!(timer, "Finalize transition for '{}/{}'", fee.program_id(), fee.function_name());
}

Expand All @@ -148,7 +148,7 @@ impl<N: Network> Process<N> {
// Retrieve the stack.
let stack = self.get_stack(fee.program_id())?;
// Finalize the fee transition.
let result = finalize_fee_transition(state, store, stack, fee);
let result = finalize_fee_transition(state, store, &stack, fee);
finish!(timer, "Finalize transition for '{}/{}'", fee.program_id(), fee.function_name());
// Return the result.
result
Expand Down Expand Up @@ -520,7 +520,7 @@ function compute:
.unwrap();

// Initialize a new process.
let mut process = Process::load().unwrap();
let process = Process::load_testing_only().unwrap();
// Deploy the program.
let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap();

Expand All @@ -538,7 +538,7 @@ function compute:
let (stack, _) =
process.finalize_deployment(sample_finalize_state(1), &finalize_store, &deployment, &fee).unwrap();
// Add the stack *manually* to the process.
process.add_stack(stack);
process.add_stack(Arc::new(stack)).unwrap();

// Ensure the program exists.
assert!(process.contains_program(program.id()));
Expand Down
Loading