This commit is contained in:
Gavin Wood
2021-04-14 10:54:35 +02:00
committed by GitHub
parent 86f9a99184
commit 09cd8a8976
2 changed files with 33 additions and 3 deletions
+7 -2
View File
@@ -336,9 +336,14 @@ decl_module! {
maximum_channels, maximum_channels,
); );
// Note conversion to the OutboundHrmpMessage isn't needed since the data that // Note conversion to the `OutboundHrmpMessage` isn't needed since the data that
// `take_outbound_messages` returns encodes equivalently. // `take_outbound_messages` returns encodes equivalently.
// If the following code breaks, then we'll need to revisit that assumption. //
// The following code is a smoke test to check that the `OutboundHrmpMessage` type
// doesn't accidentally change (e.g. by having a field added to it). If the following
// line breaks, then we'll need to revisit the assumption that the result of
// `take_outbound_messages` can be placed into `HRMP_OUTBOUND_MESSAGES` directly without
// a decode/encode round-trip.
let _ = OutboundHrmpMessage { recipient: ParaId::from(0), data: vec![] }; let _ = OutboundHrmpMessage { recipient: ParaId::from(0), data: vec![] };
storage::unhashed::put(well_known_keys::HRMP_OUTBOUND_MESSAGES, &outbound_messages); storage::unhashed::put(well_known_keys::HRMP_OUTBOUND_MESSAGES, &outbound_messages);
+26 -1
View File
@@ -406,6 +406,31 @@ impl<T: Config> Module<T> {
/// Service the incoming XCMP message queue attempting to execute up to `max_weight` execution /// Service the incoming XCMP message queue attempting to execute up to `max_weight` execution
/// weight of messages. /// weight of messages.
///
/// Channels are first shuffled and then processed in this random one page at a time, order over
/// and over until either `max_weight` is exhausted or no channel has messages that can be
/// processed any more.
///
/// There are two obvious "modes" that we could apportion `max_weight`: one would be to attempt
/// to spend it all on the first channel's first page, then use the leftover (if any) for the
/// second channel's first page and so on until finally we cycle back and the process messages
/// on the first channel's second page &c. The other mode would be to apportion only `1/N` of
/// `max_weight` for the first page (where `N` could be, perhaps, the number of channels to
/// service, using the remainder plus the next `1/N` for the next channel's page &c.
///
/// Both modes have good qualities, the first ensures that a channel with a large message (over
/// `1/N` does not get indefinitely blocked if other channels have continuous, light traffic.
/// The second is fairer, and ensures that channels with continuous light messages don't suffer
/// high latency.
///
/// The following code is a hybrid solution; we have a concept of `weight_available` which
/// incrementally approaches `max_weight` as more channels are attempted to be processed. We use
/// the parameter `weight_restrict_decay` to control the speed with which `weight_available`
/// approaches `max_weight`, with `0` being strictly equivalent to the first aforementioned
/// mode, and `N` approximating the second. A reasonable parameter may be `1`, which makes
/// half of the `max_weight` available for the first page, then a quarter plus the remainder
/// for the second &c. though empirical and or practical factors may give rise to adjusting it
/// further.
fn service_xcmp_queue(max_weight: Weight) -> Weight { fn service_xcmp_queue(max_weight: Weight) -> Weight {
let mut status = InboundXcmpStatus::get(); // <- sorted. let mut status = InboundXcmpStatus::get(); // <- sorted.
if status.len() == 0 { if status.len() == 0 {
@@ -441,7 +466,7 @@ impl<T: Config> Module<T> {
// first round. For the second round we unlock all weight. If we come close enough // first round. For the second round we unlock all weight. If we come close enough
// on the first round to unlocking everything, then we do so. // on the first round to unlocking everything, then we do so.
if shuffle_index < status.len() { if shuffle_index < status.len() {
weight_available += (max_weight - weight_available) / weight_restrict_decay; weight_available += (max_weight - weight_available) / (weight_restrict_decay + 1);
if weight_available + threshold_weight > max_weight { if weight_available + threshold_weight > max_weight {
weight_available = max_weight; weight_available = max_weight;
} }