Skip to content

Managed dealloc: managed buffers#2114

Merged
andrei-marinica merged 23 commits intofeat/mdropfrom
mdrop-mb
Mar 16, 2026
Merged

Managed dealloc: managed buffers#2114
andrei-marinica merged 23 commits intofeat/mdropfrom
mdrop-mb

Conversation

@andrei-marinica
Copy link
Copy Markdown
Contributor

@andrei-marinica andrei-marinica commented Jul 8, 2025

Pull request overview

This PR implements managed deallocation for managed buffers, enabling ManagedBuffer to properly free its underlying VM-side storage when dropped. Key changes include making read_from_payload unsafe (due to double-drop risks), adding a Drop impl for ManagedVec that iterates and drops items when needed, and introducing a memory benchmarking tool.

Changes:

  • Enabled ManagedBuffer::drop to call drop_managed_buffer, with corresponding safety changes (unsafe fn read_from_payload, requires_drop() trait method, ManagedVec::Drop impl)
  • Converted to_arg_buffer() usages to into_arg_buffer() to avoid cloning, and used ManagedRef/ManagedRefMut to wrap borrowed handles without triggering deallocation
  • Added managed-mem-bench tool and extensive HandleMap unit tests

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 16, 2026

Contract comparison - from be956b5 to 25fdcbe

Path                                                                                             size                  has-allocator                     has-format
large-storage.wasm 1656 false None
vec-repeat.wasm 4872 ➡️ 4876 🔴 (+4) false None
single-value-repeat.wasm 4253 ➡️ 4257 🔴 (+4) false None
queue-repeat.wasm 5536 ➡️ 5540 🔴 (+4) false None
linked-list-repeat.wasm 6838 ➡️ 6842 🔴 (+4) false without message
map-repeat.wasm 7363 ➡️ 7367 🔴 (+4) false without message
set-repeat.wasm 6511 ➡️ 6515 🔴 (+4) false None
str-repeat.wasm 2733 false without message
str-repeat-mb-builder-cached.wasm 1109 false without message
str-repeat-mb-builder-basic.wasm 757 false None
send-tx-repeat.wasm 1292 false None
forwarder-queue-promises.wasm 13336 ➡️ 13533 🔴 (+197) false without message
forwarder-queue.wasm 12712 ➡️ 12908 🔴 (+196) false without message
recursive-caller.wasm 5163 false without message
local-esdt-and-nft.wasm 12568 false without message
forwarder-raw-init-async-call.wasm 2374 ➡️ 2357 🟢 (-17) false None
forwarder-raw-init-sync-call.wasm 2958 ➡️ 2938 🟢 (-20) false None
forwarder-raw.wasm 13081 ➡️ 13185 🔴 (+104) false None
vault-upgrade.wasm 708 false None
vault.wasm 8950 ➡️ 9035 🔴 (+85) false None
forwarder.wasm 49004 ➡️ 49178 🔴 (+174) false without message
proxy-test-second.wasm 2332 ➡️ 2329 🟢 (-3) false without message
parent.wasm 1999 ➡️ 1979 🟢 (-20) false None
child.wasm 3982 false without message
transfer-role-features.wasm 8605 ➡️ 8667 🔴 (+62) false without message
first-contract.wasm 3450 ➡️ 3433 🟢 (-17) false None
second-contract.wasm 1158 false None
proxy-test-first.wasm 5707 ➡️ 5719 🔴 (+12) false without message
builtin-func-features.wasm 3828 ➡️ 3820 🟢 (-8) false None
forwarder-legacy.wasm 33620 ➡️ 33668 🔴 (+48) false without message
basic-features-small-int-bug.wasm 824 false None
basic-features.wasm 85947 ➡️ 86355 🔴 (+408) false without message
basic-features-storage-bytes.wasm 541 false None
abi-tester.wasm 8607 true without message
abi-tester-ev.wasm 760 false None
rust-snippets-generator-test.wasm 4708 ➡️ 4710 🔴 (+2) false None
formatted-message-features.wasm 3613 ➡️ 3600 🟢 (-13) false without message
use-module-view.wasm 736 false None
use-module.wasm 32480 ➡️ 32776 🔴 (+296) false without message
payable-features.wasm 6046 ➡️ 5872 🟢 (-174) false None
exchange-features.wasm 1514 false None
forbidden-opcodes.wasm 842 false None
scenario-tester.wasm 1374 false None
std-contract.wasm 3469 true without message
big-float-features.wasm 6373 false without message
rust-testing-framework-tester.wasm 8552 ➡️ 8608 🔴 (+56) false None
multi-contract-alt-impl.wasm 353 false None
multi-contract-features.wasm 681 false None
multi-contract-example-feature.wasm 680 false None
multi-contract-features-view.wasm 1113 false None
panic-message-features.wasm 13036 false with message
panic-message-std.wasm 16074 false with message
erc1155-user-mock.wasm 1229 false None
lottery-erc20.wasm 12886 ➡️ 12893 🔴 (+7) false without message
erc721.wasm 2232 false None
crowdfunding-erc20.wasm 4909 ➡️ 4910 🔴 (+1) false without message
erc1155-marketplace.wasm 10602 false without message
erc1155.wasm 12016 ➡️ 12023 🔴 (+7) false without message
erc20.wasm 1887 ➡️ 1870 🟢 (-17) false None
esdt-system-sc-mock.wasm 4557 ➡️ 4623 🔴 (+66) false None
alloc-features.wasm 23260 ➡️ 23267 🔴 (+7) false without message
alloc-mem-fail.wasm 17812 ➡️ 17819 🔴 (+7) true without message
alloc-mem-leaking.wasm 23417 ➡️ 23424 🔴 (+7) false without message
multiversx-wegld-swap-sc.wasm 4265 ➡️ 4492 🔴 (+227) false None
multiversx-price-aggregator-sc.wasm 17904 ➡️ 17910 🔴 (+6) false without message
ping-pong-egld.wasm 6397 false None
multisig-full.wasm 15128 ➡️ 15130 🔴 (+2) false without message
multisig-view.wasm 5590 false None
multisig.wasm 13617 ➡️ 13442 🟢 (-175) false without message
bonding-curve-contract.wasm 14067 ➡️ 14126 🔴 (+59) false None
kitty-genetic-alg.wasm 3494 false without message
kitty-auction.wasm 9389 ➡️ 9411 🔴 (+22) false without message
kitty-ownership.wasm 12965 false without message
check-pause.wasm 1260 false None
digital-cash.wasm 9736 ➡️ 9836 🔴 (+100) false None
fractional-nfts.wasm 8305 ➡️ 8306 🔴 (+1) false without message
adder.wasm 699 false None
order-book-pair.wasm 14099 ➡️ 14229 🔴 (+130) false None
order-book-factory.wasm 3401 false None
empty.wasm 244 false None
esdt-transfer-with-fee.wasm 7505 ➡️ 7502 🟢 (-3) false without message
nft-subscription.wasm 8728 ➡️ 8840 🔴 (+112) false without message
proxy-pause.wasm 4165 ➡️ 4148 🟢 (-17) false None
seed-nft-minter.wasm 14192 ➡️ 14443 🔴 (+251) false without message
crowdfunding.wasm 3574 ➡️ 3557 🟢 (-17) false None
nft-storage-prepay.wasm 2609 ➡️ 2606 🟢 (-3) false None
crypto-bubbles.wasm 2561 ➡️ 2541 🟢 (-20) false None
crypto-zombies.wasm 9282 ➡️ 9255 🟢 (-27) false without message
nft-minter.wasm 9726 ➡️ 9725 🟢 (-1) false without message
lottery-esdt.wasm 10580 ➡️ 10578 🟢 (-2) false without message
factorial.wasm 579 false None
rewards-distribution.wasm 9445 ➡️ 9553 🔴 (+108) false without message
token-release.wasm 6978 false without message

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements managed deallocation for managed buffers, enabling ManagedBuffer to properly free its underlying VM-side storage when dropped. Key changes include making read_from_payload unsafe (due to double-drop risks), adding a Drop impl for ManagedVec that iterates and drops items when needed, and introducing a memory benchmarking tool.

Changes:

  • Enabled ManagedBuffer::drop to call drop_managed_buffer, with corresponding safety changes (unsafe fn read_from_payload, requires_drop() trait method, ManagedVec::Drop impl)
  • Converted to_arg_buffer() usages to into_arg_buffer() to avoid cloning, and used ManagedRef/ManagedRefMut to wrap borrowed handles without triggering deallocation
  • Added managed-mem-bench tool and extensive HandleMap unit tests

Reviewed changes

Copilot reviewed 52 out of 53 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
framework/base/src/types/managed/basic/managed_buffer.rs Enable buffer deallocation in Drop, update clone
framework/base/src/types/managed/wrapped/managed_vec_item.rs Make read_from_payload unsafe, add requires_drop() and temp_decode
framework/base/src/types/managed/wrapped/managed_vec.rs Add Drop impl, fix forget_into_handle, update PartialEq and get_unsafe
framework/base/src/types/managed/wrapped/managed_vec_ref.rs Soft-dealloc via save_to_payload in drop
framework/base/src/types/managed/wrapped/managed_vec_ref_mut.rs Updated drop comment and structure
framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs Add unsafe to read_from_payload calls
framework/base/src/types/managed/wrapped/encoded_managed_vec_item.rs Unsafe call with TODO
framework/base/src/types/managed/multi_value/multi_value_encoded.rs Add into_arg_buffer, update to_arg_buffer to clone
framework/base/src/api/managed_types/managed_type_api_impl.rs Add requires_managed_type_drop default
framework/base/src/storage/storage_set.rs Use ManagedRef for temp handles
framework/base/src/contract_base/wrappers/blockchain_wrapper.rs Use ManagedRef for temp handles
framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs Use new_uninit for temp buffer
framework/derive/src/managed_vec_item_derive.rs Make derived read_from_payload unsafe
chain/vm/src/host/context/managed_type_container/handle_map.rs Add assert on remove, shrink heuristic, extensive tests
chain/vm/src/host/context/managed_type_container/tx_managed_buffer.rs Commented-out debug print
framework/scenario/src/api/impl_vh/*.rs Explicit dispatcher drop ordering, debug println
framework/scenario/tests/*.rs Update tests for unsafe read_from_payload / temp_decode
tools/managed-mem-bench/ New memory leak detection tool
contracts/feature-tests/composability/**/src/*.rs to_arg_buffer()into_arg_buffer()
Various token payment files Make read_from_payload unsafe

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread framework/base/src/types/managed/wrapped/managed_vec_ref_mut.rs Outdated
Comment thread tools/managed-mem-bench/README.md
Comment thread framework/base/src/types/managed/wrapped/encoded_managed_vec_item.rs Outdated
Comment thread framework/base/src/types/managed/wrapped/managed_vec.rs
Comment thread framework/base/src/contract_base/wrappers/blockchain_wrapper.rs Outdated
Comment thread framework/scenario/src/api/impl_vh/debug_handle_vh.rs Outdated
Comment thread chain/vm/src/host/context/managed_type_container/tx_managed_buffer.rs Outdated
@andrei-marinica andrei-marinica marked this pull request as ready for review March 16, 2026 14:03
@andrei-marinica andrei-marinica merged commit 049f8d9 into feat/mdrop Mar 16, 2026
32 of 34 checks passed
@andrei-marinica andrei-marinica deleted the mdrop-mb branch March 16, 2026 14:25
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