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

LPv2: Fix weights with batch messages #1951

Merged
merged 4 commits into from
Aug 9, 2024
Merged

LPv2: Fix weights with batch messages #1951

merged 4 commits into from
Aug 9, 2024

Conversation

lemunozm
Copy link
Contributor

@lemunozm lemunozm commented Aug 7, 2024

Description

  • Add max_processing_weight() method to MessageProcessor that allows to know upfront the worst case for processing a message.
  • Check the worst case before processing.
  • Adapt weight to work fine with batches

TODOS

@lemunozm lemunozm requested review from cdamian and wischli August 7, 2024 17:36
@lemunozm lemunozm self-assigned this Aug 7, 2024
Copy link
Contributor Author

@lemunozm lemunozm left a 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.

Comment on lines +124 to +128
#[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(
Copy link
Contributor Author

@lemunozm lemunozm Aug 7, 2024

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

Comment on lines 208 to 214
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;
}
Copy link
Contributor Author

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 {
Copy link
Contributor Author

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

Comment on lines -548 to -558
// 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)),
)
Copy link
Contributor Author

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.

Copy link
Contributor Author

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

Comment on lines 623 to 616
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 */
}
}
Copy link
Contributor Author

@lemunozm lemunozm Aug 7, 2024

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.

@lemunozm lemunozm force-pushed the lpv2/fix-weights branch 2 times, most recently from 1f1356c to 3eb4bff Compare August 8, 2024 09:35
@lemunozm lemunozm changed the base branch from lpv2/batch-logic-r2 to main August 8, 2024 09:35
@lemunozm lemunozm marked this pull request as ready for review August 8, 2024 09:35
Copy link

codecov bot commented Aug 8, 2024

Codecov Report

Attention: Patch coverage is 76.00000% with 6 lines in your changes missing coverage. Please review.

Project coverage is 47.97%. Comparing base (4bfeabe) to head (cac1931).

Files Patch % Lines
pallets/liquidity-pools-gateway/src/lib.rs 28.57% 5 Missing ⚠️
pallets/liquidity-pools-gateway/queue/src/lib.rs 92.30% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@cdamian cdamian left a 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.

@lemunozm
Copy link
Contributor Author

lemunozm commented Aug 9, 2024

You should not be too many, because the parts I modify you don't 🤞🏻. @wischli tell me if you have some comments regarding this post-mortem, to merge this ASAP for @cdamian

@lemunozm lemunozm merged commit e0d2230 into main Aug 9, 2024
12 checks passed
Copy link
Contributor

@wischli wischli left a 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)
Copy link
Contributor

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.

Copy link
Contributor Author

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants