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

add elastic scaling MVP guide #4663

Merged
merged 7 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
135 changes: 135 additions & 0 deletions docs/sdk/src/guides/enable_elastic_scaling_mvp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
//! # Enable elastic scaling MVP for a parachain
//!
//! **This guide assumes full familiarity with Asynchronous Backing and its terminology, as defined
//! in <https://wiki.polkadot.network/docs/maintain-guides-async-backing>.
//! Furthermore, the parachain should have already been upgraded according to the guide.**
Copy link
Contributor

@kianenigma kianenigma Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also link to #4363 once it is merged.

Moreover, I think you can also benefit a bit from the suggestiosn similar to #4363 (comment)

PTAL: https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/meta_contributing/index.html#why-rust-docs

//!
//! ## Quick introduction to elastic scaling
//!
//! [Elastic scaling](https://polkadot.network/blog/elastic-scaling-streamling-growth-on-polkadot)
//! is a feature that will enable parachains to seamlessly scale up or down the amount of block
//! validated and backed in a single relay chain block, in order to keep up with demand.
alindima marked this conversation as resolved.
Show resolved Hide resolved
//!
//! At present, with Asynchronous Backing enabled, a parachain can only include a block on the relay
//! chain every 6 seconds, irregardless of how many cores the parachain acquires. Elastic scaling
//! builds further on the 10x throughput increase of Async Backing, enabling collators to submit up
//! to 3 parachain blocks per relay chain block, resulting in a further 3x throughput increase.
//!
//! ## Current limitations of the MVP
//!
//! The full implementation of elastic scaling spans across the entire relay/parachain stack and is
//! still [work in progress](https://github.com/paritytech/polkadot-sdk/issues/1829).
//! Below are described the current limitations of the MVP:
//!
//! 1. **A parachain can use at most 3 cores at a time.** This limitation stems from the fact that
alindima marked this conversation as resolved.
Show resolved Hide resolved
//! every parablock has an execution timeout of 2 seconds and the relay chain block authoring
//! takes 6 seconds. Therefore, assuming parablock authoring is sequential, a collator only has
alindima marked this conversation as resolved.
Show resolved Hide resolved
//! enough time to build 3 candidates in a relay chain slot.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes that using full 2s of execution is the only usecase, it is also possible to use little computation but reach PoV limit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I created this guide assuming parachains that want to use multiple cores would do so to achieve higher throughput, but it can be also used to achieve lower latency (at least to inclusion in a candidate). I'll rephrase

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

higher throughput,

can also mean more data.

//! 2. **Collator set must be of size 1 for consistently scaling beyond a core at full authorship
//! duration of 2 seconds per block.** In practice, parablock authorship takes about the same
//! amount of time as parablock import. Therefore, each collator must first import the previous
//! block before authoring a new one. For a core count of 3, this would amount to 12 seconds and
//! for a core count of 2, 8 seconds.
alindima marked this conversation as resolved.
Show resolved Hide resolved
//! 3. **Trusted collator set.** The collator set needs to be trusted until there’s a mitigation
alindima marked this conversation as resolved.
Show resolved Hide resolved
//! that would prevent or deter multiple collators from submitting the same collation.
//! 4. **Fixed scaling.** For true elasticity, the parachain must be able to seamlessly acquire or
//! sell coretime as the user demand grows and shrinks over time, in an automated manner. This is
//! currently lacking - a parachain can only scale up or down by “manually” acquiring coretime.
//! We call this fixed scaling.
alindima marked this conversation as resolved.
Show resolved Hide resolved
//!
//! ## Using elastic scaling MVP
//!
//! ### Prerequisites
//!
//! - Ensure Asynchronous Backing is enabled on the network and you have enabled it on the parachain
//! using [this guide](https://wiki.polkadot.network/docs/maintain-guides-async-backing).
//! - Ensure the `AsyncBackingParams.max_candidate_depth` value is configured as 6 on the relay
//! chain (which will allow a max velocity of 3 for each parachain).
//! - Have a trusted collator set for the parachain (of size 1 for full throughput)
alindima marked this conversation as resolved.
Show resolved Hide resolved
//! - The parachain has bought coretime for one or more cores (up to three) and is scheduled on the
alindima marked this conversation as resolved.
Show resolved Hide resolved
//! relay chain.
//! - Use the latest cumulus release, which includes the necessary elastic scaling changes
//!
//! The following steps assume using the cumulus parachain template.
//!
//! ### Phase 1 - Update Parachain Node
//!
//! This phase consists of plugging in the new slot-based collator node.
//!
//! 1. In `node/src/service.rs` import the slot based collator instead of the lookahead collator.
//!
//! ```rust
//! use cumulus_client_consensus_aura::collators::slot_based::{self as aura, Params as AuraParams};
//! ```
//!
//! 2. In `start_consensus()`
kianenigma marked this conversation as resolved.
Show resolved Hide resolved
//! - Remove the `overseer_handle` param (also remove the
//! `OverseerHandle` type import if it’s not used elsewhere).
//! - In `AuraParams`, remove the `sync_oracle` and `overseer_handle` fields and add a
//! `slot_drift` field with a value of `Duration::from_secs(1)`.
//! - Replace the single future returned by `aura::run` with the two futures returned by it and
//! spawn them as separate tasks:
//! ```rust
//! let (collation_future, block_builder_future) = aura::run::<
//! Block,
//! sp_consensus_aura::sr25519::AuthorityPair,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be a requirement. The slot based collator should be activated by a CLI parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section is targeted at paras that use the cumulus template, not polkadot-parachain. If they want to switch to using elastic scaling they can't just use a CLI parameter, they still need to do these steps.

Once the slot based collator is merged I'll add a section here for parachains utilising polkadot-parachain binary

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guides should be built for template/parachain, not polkadot-parachain IMO.

That being said, as noted above, I think this doc can be written better if it reuses the code of template/parachain

//! _,
//! _,
//! _,
//! _,
//! _,
//! _,
//! _,
//! _>(params);
//! task_manager
//! .spawn_essential_handle()
//! .spawn("collation-task", None, collation_future);
//! task_manager
//! .spawn_essential_handle()
//! .spawn("block-builder-task", None, block_builder_future);
//! ```
//!
//! 3. In `start_parachain_node()` remove the `sync_service` and `overseer_handle` params passed to
//! `start_consensus`
//!
//! ### Phase 2 - Activate fixed factor scaling in the runtime
//!
//! This phase consists of a couple of changes needed to be made to the parachain’s runtime in order
//! to utilise fixed factor scaling.
//!
//! First of all, you need to decide how many parachain blocks you need to produce per relay chain
//! block (in direct correlation with the number of acquired cores). This should be either 1 (no
//! scaling), 2 or 3. This is called the parachain velocity.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they should decide what is minimum block time (MIN_SLOT_TIME) of the elastic parachain. This also means we don't need to change this value. Actual block production rate would be controlled by the amount of coretime available to the parachain at given RCB

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the outcome is the same as deciding on the maximum velocity

//!
//! If you configure a velocity which is different from the number of assigned cores, the measured
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just compute the rest of the values based on the minimum parachain block time (MIN_SLOT_DURATION)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes they can. I specifically say how they all relate to each other and the formulas to derive them. I think the parachain teams can decide how to code them, this is just an example

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the constant computations based on maximum velocity

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely have seen this velocity stuff in the async backing guides PR as well, I think it is best to first push that to completion in the best possible shape, then build this on top of it.

//! velocity in practice will be the minimum of these two.
//!
//! The chosen velocity should also be used to compute:
//! - The slot duration, by dividing the 6000 ms duration of the relay chain slot duration by the
//! velocity.
//! - The unincluded segment capacity, by multiplying the velocity with 2 and adding 1 to
//! it.
//!
//! Let’s assume a desired velocity of 3 parachain blocks per relay chain block. The needed changes
//! would all be done in `runtime/src/lib.rs`:
//!
//! 1. Increase the `BLOCK_PROCESSING_VELOCITY` to the desired value. In this example, 3.
//!
//! ```rust
//! const BLOCK_PROCESSING_VELOCITY: u32 = 3;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//! const BLOCK_PROCESSING_VELOCITY: u32 = 3;
//! const BLOCK_PROCESSING_VELOCITY: u32 = (RELAY_CHAIN_SLOT_TIME / MIN_SLOT_DURATION);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use docify please :)

//! ```
//!
//! 2. Decrease the `MILLISECS_PER_BLOCK` to the desired value. In this example, 2000.
//!
//! ```rust
//! const MILLISECS_PER_BLOCK: u32 = 2000;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//! const MILLISECS_PER_BLOCK: u32 = 2000;
//! const MILLISECS_PER_BLOCK: u32 = MIN_SLOT_DURATION;

//! ```
//! Note: for a parachain which measures time in terms of its own block number, changing block
//! time may cause complications, requiring additional changes. See the section ["Timing by
//! block number" of the async backing guide](https://wiki.polkadot.network/docs/maintain-guides-async-backing#timing-by-block-number).
//!
//! 3. Increase the `UNINCLUDED_SEGMENT_CAPACITY` to the desired value. In this example, 7.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is 7 to work around the bug in the collator. We should fix it :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see any open issue for it. Is there one? Have we ever confirmed what the bug is?

The relay chain also adds +1 to the max_candidate_depth, so in reality this is no different from that value

//!
//! ```rust
//! const UNINCLUDED_SEGMENT_CAPACITY: u32 = 7;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//! const UNINCLUDED_SEGMENT_CAPACITY: u32 = 7;
//! const UNINCLUDED_SEGMENT_CAPACITY: u32 = (RELAY_CHAIN_SLOT_TIME / MIN_SLOT_TIME)*2;

//! ```
3 changes: 3 additions & 0 deletions docs/sdk/src/guides/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ pub mod enable_pov_reclaim;

/// How to enable metadata hash verification in the runtime.
pub mod enable_metadata_hash;

/// How to enable elastic scaling MVP on a parachain.
pub mod enable_elastic_scaling_mvp;
Loading