Skip to content

Commit

Permalink
feat: optimize LWG and NWG (#2512)
Browse files Browse the repository at this point in the history
## What ❔

Separating recursive circuits from the AggregationWrapper struct allows
them to be used separately and significantly reduces data duplication in
the storage.

Processing L/N circuits in parallel speeds up processing, also providing
an adjustable limits on peak memory.
  • Loading branch information
0xVolosnikov authored Aug 2, 2024
1 parent 2e7ca71 commit 0d00650
Show file tree
Hide file tree
Showing 9 changed files with 504 additions and 279 deletions.
76 changes: 38 additions & 38 deletions Cargo.lock

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

18 changes: 11 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -197,19 +197,23 @@ trybuild = "1.0"
vise = "0.1.0"
vise-exporter = "0.1.0"

circuit_sequencer_api_1_3_3 = { package = "circuit_sequencer_api", version = "=0.133.0" }
circuit_sequencer_api_1_4_0 = { package = "circuit_sequencer_api", version = "=0.140.0" }
circuit_sequencer_api_1_4_1 = { package = "circuit_sequencer_api", version = "=0.141.0" }
circuit_sequencer_api_1_4_2 = { package = "circuit_sequencer_api", version = "=0.142.0" }
circuit_sequencer_api_1_5_0 = { package = "circuit_sequencer_api", version = "=0.150.2-rc.1" }
# Here and below:
# We *always* pin the latest version of protocol to disallow accidental changes in the execution logic.
# However, for the historical version of protocol crates, we have lax requirements. Otherwise,
# Bumping a crypto dependency like `boojum` would require us to republish all the historical packages.
circuit_sequencer_api_1_3_3 = { package = "circuit_sequencer_api", version = "0.133" }
circuit_sequencer_api_1_4_0 = { package = "circuit_sequencer_api", version = "0.140" }
circuit_sequencer_api_1_4_1 = { package = "circuit_sequencer_api", version = "0.141" }
circuit_sequencer_api_1_4_2 = { package = "circuit_sequencer_api", version = "0.142" }
circuit_sequencer_api_1_5_0 = { package = "circuit_sequencer_api", version = "=0.150.2-rc.2" }
crypto_codegen = { package = "zksync_solidity_vk_codegen", version = "=0.1.0" }
kzg = { package = "zksync_kzg", version = "=0.150.2-rc.1" }
kzg = { package = "zksync_kzg", version = "=0.150.2-rc.2" }
zk_evm = { version = "=0.133.0" }
zk_evm_1_3_1 = { package = "zk_evm", version = "0.131.0-rc.2" }
zk_evm_1_3_3 = { package = "zk_evm", version = "0.133.0" }
zk_evm_1_4_0 = { package = "zk_evm", version = "0.140.0" }
zk_evm_1_4_1 = { package = "zk_evm", version = "0.141.0" }
zk_evm_1_5_0 = { package = "zk_evm", version = "0.150.0" }
zk_evm_1_5_0 = { package = "zk_evm", version = "=0.150.0" }

# Consensus dependencies.
zksync_concurrency = "=0.1.0-rc.5"
Expand Down
18 changes: 13 additions & 5 deletions core/lib/config/src/configs/fri_witness_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,20 @@ pub struct FriWitnessGeneratorConfig {

pub prometheus_listener_port: Option<u16>,

/// This value corresponds to the maximum number of circuits kept in memory at any given time for a BWG.
/// This value corresponds to the maximum number of circuits kept in memory at any given time for a BWG/LWG/NWG.
/// Acts as a throttling mechanism for circuits; the trade-off here is speed vs memory usage.
///
/// BWG:
/// With more circuits in flight, harness does not need to wait for BWG runner to process them.
/// But every single circuit in flight eats memory (up to 50MB).
///
/// LWG/NWG:
/// Each circuit is processed in parallel.
/// Each circuit requires downloading RECURSION_ARITY (32) proofs, each of which can be roughly estimated at 1 MB.
/// So every single circuit should use ~32 MB of RAM + some overhead during serialization
///
/// WARNING: Do NOT change this value unless you're absolutely sure you know what you're doing.
/// It affects the performance and resource usage of BWGs.
/// It affects the performance and resource usage of WGs.
#[serde(default = "FriWitnessGeneratorConfig::default_max_circuits_in_flight")]
pub max_circuits_in_flight: usize,
}
Expand Down Expand Up @@ -97,10 +105,10 @@ impl FriWitnessGeneratorConfig {
self.last_l1_batch_to_process.unwrap_or(u32::MAX)
}

/// 500 was picked as a mid-ground between allowing enough circuits in flight to speed up circuit generation,
/// whilst keeping memory as low as possible. At the moment, max size of a circuit is ~50MB.
/// 500 was picked as a mid-ground between allowing enough circuits in flight to speed up BWG circuit generation,
/// whilst keeping memory as low as possible. At the moment, max size of a circuit in BWG is ~50MB.
/// This number is important when there are issues with saving circuits (network issues, service unavailability, etc.)
/// Maximum theoretic extra memory consumed is up to 25GB (50MB * 500 circuits), but in reality, worse case scenarios are closer to 5GB (the average space distribution).
/// Maximum theoretic extra memory consumed by BWG is up to 25GB (50MB * 500 circuits), but in reality, worse case scenarios are closer to 5GB (the average space distribution).
/// During normal operations (> P95), this will incur an overhead of ~100MB.
const fn default_max_circuits_in_flight() -> usize {
500
Expand Down
Loading

0 comments on commit 0d00650

Please sign in to comment.