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

Skip idle_scheduler Calls When Not Producing blocks #1721

Merged
merged 31 commits into from
Apr 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9fdb35e
initial attempt
ferrell-code Dec 21, 2021
710998b
use relaychain blocks
ferrell-code Dec 22, 2021
c00b058
comments
ferrell-code Dec 22, 2021
a09c075
testing
ferrell-code Dec 23, 2021
7796294
use previous relayblock number
ferrell-code Dec 28, 2021
f4552a7
fix mock
ferrell-code Dec 28, 2021
c7ebdc2
Merge remote-tracking branch 'upstream/master' into fer-check-idle
ferrell-code Dec 28, 2021
16f9750
review feedback
ferrell-code Dec 28, 2021
3500564
suggested rename and fix mocks
ferrell-code Jan 20, 2022
b4b571e
Merge remote-tracking branch 'upstream/master' into fer-check-idle
ferrell-code Jan 20, 2022
1127d60
one more mock
ferrell-code Jan 20, 2022
14dba36
clean up and add benchmarking
ferrell-code Mar 30, 2022
e26a985
conflicts
ferrell-code Mar 30, 2022
4b602b7
no need to benchmark unexposed call
ferrell-code Mar 30, 2022
07ca8b2
add tests
ferrell-code Mar 31, 2022
7eba83f
fix mock'
ferrell-code Mar 31, 2022
3cd502b
some of review
ferrell-code Apr 4, 2022
d7f73c3
conflicts
ferrell-code Apr 4, 2022
9ca309b
fix test
ferrell-code Apr 4, 2022
35e3b2d
add benchmarks
ferrell-code Apr 4, 2022
e5a0ba0
add to tests
ferrell-code Apr 4, 2022
418c8bb
more comprehensive benchmarking
ferrell-code Apr 4, 2022
89ce4da
fix tests
ferrell-code Apr 4, 2022
96ed727
return total weight
ferrell-code Apr 4, 2022
18ad1af
subtract clear_tasks weight while still in loop to not go overweight
ferrell-code Apr 4, 2022
fc2e951
fix benchmark
ferrell-code Apr 4, 2022
e3fc8bb
Merge branch 'master' into fer-check-idle
ferrell-code Apr 6, 2022
a376298
conflicts
ferrell-code Apr 7, 2022
37fe8be
unify BlockNumber
ferrell-code Apr 7, 2022
cd559c5
update evm-tests
ferrell-code Apr 7, 2022
9c2b58a
conflicts
ferrell-code Apr 7, 2022
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
2 changes: 1 addition & 1 deletion evm-tests
15 changes: 14 additions & 1 deletion modules/evm/src/bench/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use primitives::{
};
use sp_core::{H160, H256};
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
traits::{BlakeTwo256, BlockNumberProvider, IdentityLookup},
AccountId32,
};

Expand Down Expand Up @@ -141,13 +141,26 @@ define_combined_task! {

parameter_types!(
pub MinimumWeightRemainInBlock: Weight = u64::MIN;
pub const DisableBlockThreshold: BlockNumber = 6;
);

pub struct MockBlockNumberProvider;

impl BlockNumberProvider for MockBlockNumberProvider {
type BlockNumber = u32;

fn current_block_number() -> Self::BlockNumber {
Zero::zero()
}
}

impl module_idle_scheduler::Config for Runtime {
type Event = Event;
type WeightInfo = ();
type Task = ScheduledTasks;
type MinimumWeightRemainInBlock = MinimumWeightRemainInBlock;
type RelayChainBlockNumberProvider = MockBlockNumberProvider;
type DisableBlockThreshold = DisableBlockThreshold;
}

pub struct GasToWeight;
Expand Down
15 changes: 14 additions & 1 deletion modules/evm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use primitives::{define_combined_task, Amount, BlockNumber, CurrencyId, ReserveI
use sp_core::{H160, H256};
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
traits::{BlakeTwo256, BlockNumberProvider, IdentityLookup},
AccountId32,
};
use std::{collections::BTreeMap, str::FromStr};
Expand Down Expand Up @@ -140,13 +140,26 @@ define_combined_task! {

parameter_types!(
pub MinimumWeightRemainInBlock: Weight = u64::MIN;
pub DisableBlockThreshold: BlockNumber = u32::MAX;
);

pub struct MockBlockNumberProvider;

impl BlockNumberProvider for MockBlockNumberProvider {
type BlockNumber = u32;

fn current_block_number() -> Self::BlockNumber {
Zero::zero()
}
}

impl module_idle_scheduler::Config for Runtime {
type Event = Event;
type WeightInfo = ();
type Task = ScheduledTasks;
type MinimumWeightRemainInBlock = MinimumWeightRemainInBlock;
type RelayChainBlockNumberProvider = MockBlockNumberProvider;
type DisableBlockThreshold = DisableBlockThreshold;
}

pub struct GasToWeight;
Expand Down
67 changes: 60 additions & 7 deletions modules/idle-scheduler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::unused_unit)]
#![allow(unused_must_use)]
use acala_primitives::{task::TaskResult, Nonce};
use acala_primitives::{task::TaskResult, BlockNumber, Nonce};
use codec::FullCodec;
use frame_support::log;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
pub use module_support::{DispatchableTask, IdleScheduler};
use scale_info::TypeInfo;
use sp_runtime::{
traits::{One, Zero},
traits::{BlockNumberProvider, One},
ArithmeticError,
};
use sp_std::{cmp::PartialEq, fmt::Debug, prelude::*};
Expand Down Expand Up @@ -58,6 +59,15 @@ pub mod module {
/// The minimum weight that should remain before idle tasks are dispatched.
#[pallet::constant]
type MinimumWeightRemainInBlock: Get<Weight>;

/// Gets RelayChain Block Number
type RelayChainBlockNumberProvider: BlockNumberProvider<BlockNumber = BlockNumber>;

/// Number of Relay Chain blocks skipped to disable `on_idle` dispatching scheduled tasks
/// this shuts down idle-scheduler when block production is slower than this number of
/// relaychain blocks
#[pallet::constant]
type DisableBlockThreshold: Get<BlockNumber>;
}

#[pallet::event]
Expand All @@ -76,14 +86,50 @@ pub mod module {
#[pallet::getter(fn next_task_id)]
pub type NextTaskId<T: Config> = StorageValue<_, Nonce, ValueQuery>;

///
#[pallet::storage]
#[pallet::getter(fn previous_relay_block)]
pub type PreviousRelayBlockNumber<T: Config> = StorageValue<_, BlockNumber, ValueQuery>;

#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);

#[pallet::hooks]
impl<T: Config> Hooks<T::BlockNumber> for Pallet<T> {
fn on_initialize(_n: T::BlockNumber) -> Weight {
// This is the previous relay block because `on_initialize` is executed
// before the inherent that sets the new relay chain block number
let previous_relay_block: BlockNumber = T::RelayChainBlockNumberProvider::current_block_number();

PreviousRelayBlockNumber::<T>::put(previous_relay_block);
T::WeightInfo::on_initialize()
}

fn on_idle(_n: T::BlockNumber, remaining_weight: Weight) -> Weight {
Self::do_dispatch_tasks(remaining_weight)
// Checks if we have skipped enough relay blocks without block production to skip dispatching
// scheduled tasks
let current_relay_block_number: BlockNumber = T::RelayChainBlockNumberProvider::current_block_number();
let previous_relay_block_number = PreviousRelayBlockNumber::<T>::take();
if current_relay_block_number.saturating_sub(previous_relay_block_number) >= T::DisableBlockThreshold::get()
{
log::debug!(
target: "idle-scheduler",
"Relaychain produced blocks without finalizing parachain blocks. Idle-scheduler will not execute.\ncurrent relay block number: {:?}\nprevious relay block number: {:?}",
current_relay_block_number,
previous_relay_block_number
);
// something is not correct so exaust all remaining weight (note: any on_idle hooks after
// IdleScheduler won't execute)
remaining_weight
} else {
Self::do_dispatch_tasks(remaining_weight)
}
}

fn on_finalize(_n: T::BlockNumber) {
// Don't commit to storage, needed for the case block is full and `on_idle` isn't called
PreviousRelayBlockNumber::<T>::kill();
}
}

Expand Down Expand Up @@ -116,9 +162,10 @@ impl<T: Config> Pallet<T> {

/// Keep dispatching tasks in Storage, until insufficient weight remains.
pub fn do_dispatch_tasks(total_weight: Weight) -> Weight {
let mut weight_remaining = total_weight;
let mut weight_remaining = total_weight.saturating_sub(T::WeightInfo::on_idle_base());
if weight_remaining <= T::MinimumWeightRemainInBlock::get() {
return Zero::zero();
// return total weight so no `on_idle` hook will execute after IdleScheduler
return total_weight;
}

let mut completed_tasks: Vec<(Nonce, TaskResult)> = vec![];
Expand All @@ -128,6 +175,7 @@ impl<T: Config> Pallet<T> {
weight_remaining = weight_remaining.saturating_sub(result.used_weight);
if result.finished {
completed_tasks.push((id, result));
weight_remaining = weight_remaining.saturating_sub(T::WeightInfo::clear_tasks());
}

// If remaining weight falls below the minimmum, break from the loop.
Expand All @@ -136,6 +184,13 @@ impl<T: Config> Pallet<T> {
}
}

Self::remove_completed_tasks(completed_tasks);

total_weight.saturating_sub(weight_remaining)
}

// Removes completed tasks and deposits events
pub fn remove_completed_tasks(completed_tasks: Vec<(Nonce, TaskResult)>) {
// Deposit event and remove completed tasks.
for (id, result) in completed_tasks {
Self::deposit_event(Event::<T>::TaskDispatched {
Expand All @@ -144,8 +199,6 @@ impl<T: Config> Pallet<T> {
});
Tasks::<T>::remove(id);
}

total_weight.saturating_sub(weight_remaining)
}
}

Expand Down
18 changes: 18 additions & 0 deletions modules/idle-scheduler/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ use acala_primitives::{define_combined_task, task::TaskResult};
use frame_support::weights::Weight;
use frame_support::{construct_runtime, parameter_types, traits::Everything};
use module_support::DispatchableTask;
pub use sp_runtime::offchain::storage::StorageValueRef;

use super::*;
use codec::{Decode, Encode};
use scale_info::TypeInfo;

pub const BASE_WEIGHT: Weight = 1_000_000;
pub const RELAY_BLOCK_KEY: [u8; 32] = [0; 32];

parameter_types!(
pub const BlockHashCount: u32 = 250;
Expand Down Expand Up @@ -65,13 +68,27 @@ impl frame_system::Config for Runtime {

parameter_types!(
pub const MinimumWeightRemainInBlock: Weight = 100_000_000_000;
pub const DisableBlockThreshold: BlockNumber = 6;
);

pub struct MockBlockNumberProvider;

impl BlockNumberProvider for MockBlockNumberProvider {
type BlockNumber = u32;

fn current_block_number() -> Self::BlockNumber {
// gets a local mock storage value
u32::decode(&mut &sp_io::storage::get(&RELAY_BLOCK_KEY).unwrap()[..]).unwrap()
}
}

impl module_idle_scheduler::Config for Runtime {
type Event = Event;
type WeightInfo = ();
type Task = ScheduledTasks;
type MinimumWeightRemainInBlock = MinimumWeightRemainInBlock;
type RelayChainBlockNumberProvider = MockBlockNumberProvider;
type DisableBlockThreshold = DisableBlockThreshold;
}

// Mock dispatachable tasks
Expand Down Expand Up @@ -137,6 +154,7 @@ impl ExtBuilder {

let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(|| System::set_block_number(1));
ext.execute_with(|| sp_io::storage::set(&RELAY_BLOCK_KEY, &0_u32.encode()));
ext
}
}
32 changes: 28 additions & 4 deletions modules/idle-scheduler/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ fn can_process_tasks_up_to_weight_limit() {
ScheduledTasks::HomaLiteTask(HomaLiteTask::OnIdle)
));

// Given enough weights for only 2 tasks: MinimumWeightRemainInBlock::get() + BASE_WEIGHT*2
IdleScheduler::on_idle(0, 100_002_000_000);
// Given enough weights for only 2 tasks: MinimumWeightRemainInBlock::get() + BASE_WEIGHT*2 +
// on_idle_base()
IdleScheduler::on_idle(0, 100_002_000_000 + <()>::on_idle_base() + (<()>::clear_tasks() * 2));

// Due to hashing, excution is not guaranteed to be in order.
assert_eq!(
Expand All @@ -80,13 +81,13 @@ fn can_process_tasks_up_to_weight_limit() {
assert_eq!(Tasks::<Runtime>::get(1), None);
assert_eq!(Tasks::<Runtime>::get(2), None);

IdleScheduler::on_idle(0, 100_000_000_000);
IdleScheduler::on_idle(0, 100_000_000_000 + <()>::on_idle_base());
assert_eq!(
Tasks::<Runtime>::get(0),
Some(ScheduledTasks::BalancesTask(BalancesTask::OnIdle))
);

IdleScheduler::on_idle(0, 100_001_000_000);
IdleScheduler::on_idle(0, 100_001_000_000 + <()>::on_idle_base());
assert_eq!(Tasks::<Runtime>::get(0), None);
});
}
Expand All @@ -104,3 +105,26 @@ fn can_increment_next_task_id() {
assert_eq!(NextTaskId::<Runtime>::get(), 1);
});
}

#[test]
fn on_idle_works() {
ExtBuilder::default().build().execute_with(|| {
IdleScheduler::on_initialize(0);
assert_ok!(IdleScheduler::schedule_task(
Origin::root(),
ScheduledTasks::BalancesTask(BalancesTask::OnIdle)
));
// simulate relay block number jumping 10 blocks
sp_io::storage::set(&RELAY_BLOCK_KEY, &10_u32.encode());
assert_eq!(IdleScheduler::on_idle(System::block_number(), u64::MAX), u64::MAX);

System::set_block_number(1);
IdleScheduler::on_initialize(1);
// On_initialize is called it will execute, as now relay block number is the same
assert_eq!(
IdleScheduler::on_idle(System::block_number(), u64::MAX),
BASE_WEIGHT + <()>::on_idle_base() + <()>::clear_tasks()
);
assert!(!PreviousRelayBlockNumber::<Runtime>::exists());
});
}
Loading