Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Scheduler Module #1162

Merged
merged 40 commits into from
Jun 11, 2020
Merged

Scheduler Module #1162

merged 40 commits into from
Jun 11, 2020

Conversation

rphmeier
Copy link
Contributor

@rphmeier rphmeier commented May 28, 2020

Fixes #1145

This implements the Scheduler module from the implementor's guide. It makes some small adjustments to the guide as well, as certain invariants needed cleaning up.

The implementation itself is done, but I still need to add a few tests. In the meantime review on the main body of code can already begin.

@rphmeier rphmeier added the A3-in_progress Pull request is in progress. No review needed at this stage. label May 28, 2020
@rphmeier rphmeier force-pushed the rh-para-scheduler branch 2 times, most recently from f771d9a to f0ea8a1 Compare May 30, 2020 04:31
@rphmeier rphmeier added the B0-silent Changes should not be mentioned in any release notes label Jun 1, 2020
@rphmeier rphmeier added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. labels Jun 6, 2020
@rphmeier rphmeier marked this pull request as ready for review June 6, 2020 19:13
decl_storage! {
trait Store for Module<T: Trait> as ParaScheduler {
/// All the validator groups. One for each core.
ValidatorGroups: Vec<Vec<ValidatorIndex>>;
Copy link
Member

@shawntabrizi shawntabrizi Jun 7, 2020

Choose a reason for hiding this comment

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

Could you annotate length bounds for the vectors used in storage?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"one for each core" is already kind of a length bound

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added some more concrete length bounds. follow-up PR welcome to re-format or rephrase

Copy link
Contributor

@drahnr drahnr left a comment

Choose a reason for hiding this comment

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

A few minor nitpicks, a more in detail review than a birds-eye-review. Comparing to the guide was done partially.

@@ -605,25 +609,37 @@ struct ParathreadEntry {
// A queued parathread entry, pre-assigned to a core.
Copy link
Contributor

Choose a reason for hiding this comment

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

Use doc comments /// instead of //

roadmap/implementors-guide/guide.md Outdated Show resolved Hide resolved
roadmap/implementors-guide/guide.md Outdated Show resolved Hide resolved
runtime/parachains/src/scheduler.rs Show resolved Hide resolved
//! manipulate the scheduler to assign themselves as desired.
//! - High or close to optimal throughput of parachains and parathreads. Work among validator groups should be balanced.
//!
//! The Scheduler manages resource allocation using the concept of "Availability Cores".
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we document the concept a bit more or directly reference what this means, if we introduce this name, state that. It's not search-engine-friendly.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree that it would be useful if this were documented in some more detail here. If not that, then at least mentioning that this is covered in more detail in the guide would help. A new programmer coming into this code base won't necessarily even know that the implementer's guide exists. They'll look at the code and at the inline documentation instead.

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 guide has a lot of detail on this concept, but PRs welcome to improve it!

runtime/parachains/src/scheduler.rs Show resolved Hide resolved
runtime/parachains/src/scheduler.rs Show resolved Hide resolved
runtime/parachains/src/scheduler.rs Show resolved Hide resolved
runtime/parachains/src/scheduler.rs Show resolved Hide resolved
runtime/parachains/src/scheduler.rs Show resolved Hide resolved
roadmap/implementors-guide/guide.md Outdated Show resolved Hide resolved
roadmap/implementors-guide/guide.md Outdated Show resolved Hide resolved
Comment on lines 712 to 713
- Behavior undefined if any given cores were not scheduled.
- Behavior undefined if the given cores are not sorted ascending by core index
Copy link
Contributor

Choose a reason for hiding this comment

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

I get that we may not wish to pay for runtime checks of these properties, but it feels like a warning flag when we introduce the possibility of UB; those tend to be the difficult bugs to discover, when they occur. Maybe we could introduce a compilation feature like ub-checks which does do the appropriate runtime checks?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It depends what the runtime checks are.

When within the runtime, panicking is pretty much the worst thing you can do. Contrary to typical software, you don't want to fail fast and fail hard - you want to limp along in broken state and get fixed by governance.

Checks that print to console and return as no-op would be welcome.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we'd ever run with ub-checks enabled on a "real" node. Instead, they'd be a debugging tool, maybe in CI, just to ensure that the properties we expect haven't been violated.

Copy link
Contributor Author

@rphmeier rphmeier Jun 11, 2020

Choose a reason for hiding this comment

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

Agreed, although I don't perceive this as a blocker for the PR, better as a follow-on that would make a good first issue for someone

let random_hash = T::Randomness::random(&b"paras"[..]);
let len = sp_std::cmp::min(32, random_hash.as_ref().len());
buf[..len].copy_from_slice(&random_hash.as_ref()[..len]);
buf
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we care that buf always has 32-len trailing 0s?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope! In practice hash is always 32 bytes, and 0-padding it is pretty much the best option if the hash is smaller in some case. It doesn't lose us any security in any case.

In the case that the hash type is larger (again, unlikely), 32 random bytes are more than enough for our purposes.

runtime/parachains/src/paras.rs Outdated Show resolved Hide resolved
//! manipulate the scheduler to assign themselves as desired.
//! - High or close to optimal throughput of parachains and parathreads. Work among validator groups should be balanced.
//!
//! The Scheduler manages resource allocation using the concept of "Availability Cores".
Copy link
Contributor

Choose a reason for hiding this comment

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

Agree that it would be useful if this were documented in some more detail here. If not that, then at least mentioning that this is covered in more detail in the guide would help. A new programmer coming into this code base won't necessarily even know that the implementer's guide exists. They'll look at the code and at the inline documentation instead.

@@ -605,25 +609,37 @@ struct ParathreadEntry {
// A queued parathread entry, pre-assigned to a core.
struct QueuedParathread {
claim: ParathreadEntry,
core: CoreIndex,
// this value is between 0 and config.parathread_cores.
core_offset: u32,
Copy link
Contributor

Choose a reason for hiding this comment

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

In several places in this document, you remove a CoreIndex and insert something named *_offset: u32. However, down in scheduler.rs, you define a CoreIndex type anyway. This leaves me confused: is the type still necessary, just not in these places, or have the documentation and implementation gotten out of sync?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These are offsets, not core indices, so it would break an invariant that CoreIndex always refers to an actual core index, if that makes sense. I believe the implementation and guide are coherent on this.

// Queue a parathread entry to be processed.
//
// Provide the entry and the number of parathread cores, which must be greater than 0.
fn queue_entry(&mut self, entry: ParathreadEntry, n_parathread_cores: u32) {
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
fn queue_entry(&mut self, entry: ParathreadEntry, n_parathread_cores: u32) {
fn enqueue_entry(&mut self, entry: ParathreadEntry, n_parathread_cores: u32) {

With the current naming, it looks more like the Entry API than an insertion.

Copy link
Contributor

Choose a reason for hiding this comment

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

Documentation suggests that n_parathread_cores should always be equal to config.parathread_cores. Is it plausible to fetch that value from configuration within this function instead of passing it as an argument?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It would be possible to fetch from storage, but IMO it's not better for a few reasons:

  • We'd have to attach the T: Trait to this type, which would be weird
  • We'd have to decode the entire configuration for every enqueued parathread claim

runtime/parachains/src/scheduler.rs Show resolved Hide resolved
runtime/parachains/src/scheduler.rs Show resolved Hide resolved
rphmeier and others added 3 commits June 10, 2020 14:13
Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com>
Co-authored-by: Bernhard Schuster <bernhard@ahoi.io>
@rphmeier rphmeier mentioned this pull request Jun 11, 2020
@rphmeier rphmeier merged commit 1696982 into master Jun 11, 2020
@rphmeier rphmeier deleted the rh-para-scheduler branch June 11, 2020 19:15
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A0-please_review Pull request needs code review. B0-silent Changes should not be mentioned in any release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement Scheduler Module
6 participants