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

Coretime Chain: mitigate behaviour with many assignments on one core #434

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix claim queue size ([runtimes#381](https://github.com/polkadot-fellows/runtimes/pull/381), [SDK v1.14 #4691](https://github.com/paritytech/polkadot-sdk/pull/4691)).
- `pallet-referenda`: Ensure to schedule referenda earliest at the next block ([runtimes#381](https://github.com/polkadot-fellows/runtimes/pull/381), [SDK v1.14 #4823](https://github.com/paritytech/polkadot-sdk/pull/4823)).
- Don't partially modify HRMP pages ([runtimes#381](https://github.com/polkadot-fellows/runtimes/pull/381), [SDK v1.14 #4710](https://github.com/paritytech/polkadot-sdk/pull/4710)).
- Coretime Chain: mitigate behaviour with many assignments on one core ([runtimes#434][https://github.com/polkadot-fellows/runtimes/pull/434]).

#### From [#322](https://github.com/polkadot-fellows/runtimes/pull/322):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ fn transact_hardcoded_weights_are_sane() {

let coretime_root_origin = <CoretimePolkadot as Chain>::RuntimeOrigin::root();

// Create and populate schedule with some assignments on this core.
// Create and populate schedule with the worst case assignment on this core.
let mut schedule = Vec::new();
for i in 0..10 {
for i in 0..80 {
schedule.push(ScheduleItem {
mask: CoreMask::void().set(i),
assignment: CoreAssignment::Task(2000 + i),
Expand Down
86 changes: 62 additions & 24 deletions system-parachains/coretime/coretime-polkadot/src/coretime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,6 @@ impl CoretimeInterface for CoretimeAllocator {
end_hint: Option<RCBlockNumberOf<Self>>,
) {
use crate::coretime::CoretimeProviderCalls::AssignCore;
let assign_core_call =
RelayRuntimePallets::Coretime(AssignCore(core, begin, assignment, end_hint));

// Weight for `assign_core` from Polkadot runtime benchmarks:
// `ref_time` = 10177115 + (1 * 25000000) + (2 * 100000000) + (80 * 13932) = 236291675
Expand All @@ -234,28 +232,68 @@ impl CoretimeInterface for CoretimeAllocator {
// TODO check when benchmarks are rerun
let call_weight = Weight::from_parts(248_000_000, 3800);

let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
Instruction::Transact {
origin_kind: OriginKind::Native,
require_weight_at_most: call_weight,
call: assign_core_call.encode().into(),
},
]);

match PolkadotXcm::send_xcm(Here, Location::parent(), message) {
Ok(_) => log::debug!(
target: "runtime::coretime",
"Core assignment sent successfully."
),
Err(e) => log::error!(
target: "runtime::coretime",
"Core assignment failed to send: {:?}",
e
),
// The relay chain currently only allows `assign_core` to be called with a complete mask
// and only ever with increasing `begin`. The assignments must be truncated to avoid
// dropping that core's assignment completely.

// This shadowing of `assignment` is temporary and can be removed when the relay can accept
// multiple messages to assign a single core.
let assignment = if assignment.len() > 28 {
let mut total_parts = 0u16;
// Account for missing parts with a new `Idle` assignment at the start as
// `assign_core` on the relay assumes this is sorted. We'll add the rest of the
// assignments and sum the parts in one pass, so this is just initialized to 0.
let mut assignment_truncated = vec![(CoreAssignment::Idle, 0)];
// Truncate to first 27 non-idle assignments.
assignment_truncated.extend(
assignment
.into_iter()
.filter(|(a, _)| *a != CoreAssignment::Idle)
.take(27)
.inspect(|(_, parts)| total_parts += *parts)
.collect::<Vec<_>>(),
);

// Set the parts of the `Idle` assignment we injected at the start of the vec above.
assignment_truncated[0].1 = 57_600u16.saturating_sub(total_parts);
assignment_truncated
} else {
assignment
};

// The maximum number of assignments for a core in a given timeslice is 80, but only 28
// assignments fit inside the max size of an XCM, so we need to send in chunks.
for assignment_chunk in assignment.chunks(28) {
seadanda marked this conversation as resolved.
Show resolved Hide resolved
let assign_core_call = RelayRuntimePallets::Coretime(AssignCore(
core,
begin,
assignment_chunk.to_vec(),
seadanda marked this conversation as resolved.
Show resolved Hide resolved
end_hint,
));

let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
Instruction::Transact {
origin_kind: OriginKind::Native,
require_weight_at_most: call_weight,
call: assign_core_call.encode().into(),
},
]);

match PolkadotXcm::send_xcm(Here, Location::parent(), message.clone()) {
Ok(_) => log::debug!(
target: "runtime::coretime",
"Core assignment sent successfully."
),
Err(e) => log::error!(
target: "runtime::coretime",
"Core assignment failed to send: {:?}",
e
),
}
}
seadanda marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
Loading