Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Prevent double allocation of the payload when calling sp_io::storage::get #11523

Conversation

koute
Copy link
Contributor

@koute koute commented May 25, 2022

polkadot companion: paritytech/polkadot#5702

cumulus companion: paritytech/cumulus#1390

This PR fixes the issue which @kianenigma found in #11454.

See the comment in the test I've added in primitives/runtime-interface/test/src/lib.rs for a more detailed explanation of the issue.

I've also added a way to grab runtime memory allocation stats after calling into the runtime. This functionality will be expanded upon as part of the paritytech/polkadot-sdk#44 in the future; for now I've added it just so that I can write a reasonable test for this issue.

This requires the following PR to be merged into parity-scale-codec: paritytech/parity-scale-codec#342

@koute koute added A0-please_review Pull request needs code review. I9-optimisation An enhancement to provide better overall performance in terms of time-to-completion for a task. I8-footprint An enhancement to provide a smaller (system load, memory, network or disk) footprint. B0-silent Changes should not be mentioned in any release notes C1-low PR touches the given topic and has a low impact on builders. D3-trivial 🧸 PR contains trivial changes in a runtime directory that do not require an audit labels May 25, 2022
@koute koute requested a review from a team May 25, 2022 14:02
@koute koute marked this pull request as draft May 25, 2022 14:03
@koute
Copy link
Contributor Author

koute commented May 25, 2022

Converted the PR to a draft until the parity-scale-codec part is merged.

@gavofyork gavofyork marked this pull request as ready for review May 31, 2022 19:50
client/allocator/src/freeing_bump.rs Outdated Show resolved Hide resolved
/// Memory allocation stats gathered during the lifetime of the allocator.
#[derive(Clone, Debug, Default)]
#[non_exhaustive]
pub struct AllocationStats {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also track the maximum single allocation that ever happened. Maybe we can directly track this as percentage of the maximum allowed allocation?

(order.size() + HEADER_SIZE) / MAX_POSSIBLE_ALLOCATION

Copy link
Contributor Author

@koute koute Jun 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we could do that, although:

  1. personally I'd probably just track its value directly instead of a percentage (e.g. imagine we hook this data to Prometheus/Grafana and we'll change the maximum possible value in the future - we can then have a situation where some nodes can have vastly different maximum allocation sizes depending on which version of the code they're running, and those will be reported exactly the same in the stats; I'd rather just add a field with the max_possible_allocation to this struct and the percentage can be later calculated when displaying this data)

  2. there are also some other metrics I'd like to add (e.g. how many allocations were made), but I simply omitted those since this is not yet the allocation stats PR (as I've said in the other comment this is just a preliminary implementation that isn't supposed to be complete), so I'd suggest we do this in a future PR (although if you want I can add this right now; its utility will be limited though so I'm not sure there's much point?)


/// Same as `uncached_call`, except it also returns allocation statistics.
#[doc(hidden)] // We use this function in tests.
pub fn uncached_call_with_allocation_stats(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not always return the stats?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you asking why it's returning an Option? Or why isn't there just a single function instead of two where first variant returning the stats and the second not returning them?

(I assume that it's the latter, but I'll explain anyway for other people who might be reading.)

It is an Option because in theory there might not be any stats to return if we couldn't call into the runtime at all (e.g. because the passed export_name is missing). Otherwise we essentially always want to return those stats: we obviously want to do it when it returns an Ok, but we also want to do it when it returns an Err (e.g. the runtime panicks due to running out of memory).

So why have two functions? Mostly to reduce churn in this PR. This is not the allocation stats PR; I just preemptively added this so that I can write a reasonable test for the issue I'm fixing here. I intend to flesh out the allocation stats (and probably rethink the interface) in a future PR.

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
/// An implementation of freeing bump allocator.
///
/// Refer to the module-level documentation for further details.
pub struct FreeingBumpHeapAllocator {
original_heap_base: u32,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (feel free to ignore)

I know that currently this allocator is only used by wasmi and wasmtime which are currently using wasm32 modules.

But the allocator itself looks like it is designed to be generic, maybe makes sense to port all these u32 types to usize?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... well, I don't think that would be worth it currently. It'd just make the whole thing more complicated for no real gain, and besides, this allocator was designed to be used with WASM if you read some of the comments (although yes, you're right, you could just use it as-is for something else).

If we ever decide to support wasm64-unknown-unknown in the very far future then we'll have to do something with this allocator, but I don't think that day will come anytime soon.

Copy link
Member

@davxy davxy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Just remember to remove the parity-scale-codec patch from Cargo.toml :-)

@koute
Copy link
Contributor Author

koute commented Jun 20, 2022

Sorry, I didn't realize this needs companion PRs.

I've added them both for Polkadot and Cumulus; fortunately they're pretty trivial.

@koute
Copy link
Contributor Author

koute commented Jul 29, 2022

bot merge

@paritytech-processbot paritytech-processbot bot merged commit 3ca8a42 into paritytech:master Jul 29, 2022
DaviRain-Su pushed a commit to octopus-network/substrate that referenced this pull request Aug 23, 2022
…::get` (paritytech#11523)

* Expose allocation stats in `FreeingBumpHeapAllocator`

* Return allocation stats when calling into the runtime

* Bump `parity-scale-codec` to 3.1.3 (fork)

* Prevent double allocation of the payload when calling `sp_io::storage::get`

* Fix tests

* Remove unnecessary `mut`

* Enable the `bytes` feature for `parity-scale-codec` in `sp-runtime-interface`

* Update client/allocator/src/freeing_bump.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Bump `parity-scale-codec` to 3.1.3

* Fix some of the UI tests

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
ark0f pushed a commit to gear-tech/substrate that referenced this pull request Feb 27, 2023
…::get` (paritytech#11523)

* Expose allocation stats in `FreeingBumpHeapAllocator`

* Return allocation stats when calling into the runtime

* Bump `parity-scale-codec` to 3.1.3 (fork)

* Prevent double allocation of the payload when calling `sp_io::storage::get`

* Fix tests

* Remove unnecessary `mut`

* Enable the `bytes` feature for `parity-scale-codec` in `sp-runtime-interface`

* Update client/allocator/src/freeing_bump.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Bump `parity-scale-codec` to 3.1.3

* Fix some of the UI tests

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A0-please_review Pull request needs code review. B0-silent Changes should not be mentioned in any release notes C1-low PR touches the given topic and has a low impact on builders. D3-trivial 🧸 PR contains trivial changes in a runtime directory that do not require an audit I8-footprint An enhancement to provide a smaller (system load, memory, network or disk) footprint. I9-optimisation An enhancement to provide better overall performance in terms of time-to-completion for a task.
Projects
Status: done
Development

Successfully merging this pull request may close these issues.

4 participants