-
Notifications
You must be signed in to change notification settings - Fork 91
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
LPv2: Fix weights with batch messages #1951
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I leave some comment justifiying the changes, which could be not easy to understand.
#[pallet::weight(MessageQueue::<T>::get(nonce) | ||
.map(|msg| T::MessageProcessor::max_processing_weight(&msg)) | ||
.unwrap_or(T::DbWeight::get().reads(1)))] | ||
#[pallet::call_index(0)] | ||
pub fn process_message(origin: OriginFor<T>, nonce: T::MessageNonce) -> DispatchResult { | ||
pub fn process_message( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We compute the max required weight for the specific message upfront. Later the extrinsic could consume less using PostInfo
let remaining_weight = max_weight.saturating_sub(weight_used); | ||
let next_weight = T::MessageProcessor::max_processing_weight(&message); | ||
|
||
// We ensure we have still capacity in the block to process the message | ||
if remaining_weight.all_gte(next_weight) { | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to be sure we have capacity in the block before we start to compute the message. We can not add the weight later, it could be too late (even more risky with a batch with a lot of sub-messages)
use cfg_primitives::LP_DEFENSIVE_WEIGHT; | ||
use frame_support::weights::Weight; | ||
|
||
pub trait WeightInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer needed, they use T::MessageProcessor::max_processing_weight()
instead
// TODO: do we really need to return the weights in send() if later we use the | ||
// defensive ones? | ||
let (result, router_weight) = match router.send(sender, serialized) { | ||
let (result, router_weight) = match router.send(sender, message.serialize()) { | ||
Ok(dispatch_info) => (Ok(()), dispatch_info.actual_weight), | ||
Err(e) => (Err(e.error), e.post_info.actual_weight), | ||
}; | ||
|
||
( | ||
result, | ||
router_weight | ||
.unwrap_or(Weight::from_parts(LP_DEFENSIVE_WEIGHT_REF_TIME, 0)) | ||
.saturating_add(read_weight) | ||
.saturating_add(Weight::from_parts(0, serialized_len)), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After investigating this. We delegate the processing weight to the router, which should take care of the bytes sent. In case we need some extra weight, it should be added to the router.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, We need to check the current XcmDomain::overall_weight
used in production to be sure it's higher than our needs
fn max_processing_weight(msg: &Self::Message) -> Weight { | ||
match msg { | ||
GatewayMessage::Inbound { message, .. } => { | ||
LP_DEFENSIVE_WEIGHT.saturating_mul(message.unpack().len() as u64) | ||
} | ||
GatewayMessage::Outbound { .. } => LP_DEFENSIVE_WEIGHT, /* TODO can be much lower */ | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the required available weight the block should have to start processing the message. I think the outbound case can be much less, but not sure how many. We can leave it as it is because later, the real weights coming from the router will be used.
2bafd7b
to
d28c780
Compare
1f1356c
to
3eb4bff
Compare
3eb4bff
to
1a54c40
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1951 +/- ##
==========================================
+ Coverage 47.83% 47.97% +0.14%
==========================================
Files 183 183
Lines 12904 12908 +4
==========================================
+ Hits 6172 6192 +20
+ Misses 6732 6716 -16 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would've loved to avoid some of the conflicts here but it's too late for that now. Let's get this in asap so I can do another rebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Post mortem: Would love to use defensive conversion for production code (NIT). Otherwise clean and beautiful as always!
fn max_processing_weight(msg: &Self::Message) -> Weight { | ||
match msg { | ||
GatewayMessage::Inbound { message, .. } => { | ||
LP_DEFENSIVE_WEIGHT.saturating_mul(message.submessages().len() as u64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: For production code, I would like to avoid casting with as
and rather use the defensive saturated_into
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only when converting from usize
to u64
, I use as
because our machine target is no more than u64
(are they machines longer than that?)
But it seems reasonable; I'll add it to my mental list of changes!
Description
max_processing_weight()
method toMessageProcessor
that allows to know upfront the worst case for processing a message.TODOS
on_idle
tests for the event pallet. Will do it in this PR later