Low Wasm memory hook
The Internet Computer can automatically execute a special type of function called a low Wasm memory hook, which runs when the canister's available Wasm memory falls below the wasm_memory_threshold
.
This Motoko example demonstrates using the low Wasm memory hook on ICP. If you're interested in how this example is implemented in Rust, check out the Rust variation.
The example consists of a canister named low_wasm_memory_hook
that increases usage of Wasm memory in every heartbeat execution until the low Wasm memory hook is run.
Prerequisites
This example requires an installation of:
- Install the IC SDK.
- Clone the example dapp project:
git clone https://github.com/dfinity/examples
Using the example
In this example, the canister will periodically increase its memory usage (as defined in the heartbeat
function) until the low Wasm memory hook is run
when the memory usage exceeds the wasm_memory_threshold
.
Step 1: Setup project environment
Navigate into the folder containing the project's files and start a local developer environment with the commands:
cd examples/motoko/low_wasm_memory
dfx start --clean
This terminal will stay blocked, printing log messages, until the Ctrl+C
is pressed or the dfx stop
command is run.
Step 2: Open another terminal window in the same directory:
cd examples/motoko/low_wasm_memory
Step 3: Create the
low_wasm_memory_hook
canister
dfx canister create low_wasm_memory_hook
Example output:
Created a wallet canister on the "local" network for user "default" with ID "uqqxf-5h777-77774-qaaaa-cai"
low_wasm_memory_hook canister created with canister id: uxrrr-q7777-77774-qaaaq-cai
Step 4: Update canister settings
Update the canister's settings to modify the Wasm memory limit and threshold:
dfx canister update-settings low_wasm_memory_hook --wasm-memory-limit 5000000 --wasm-memory-threshold 2000000
Step 5: Compile and deploy the
low_wasm_memory_hook
canister:
dfx deploy low_wasm_memory_hook
Example output:
Deploying: low_wasm_memory_hook
All canisters have already been created.
Building canister 'low_wasm_memory_hook'.
Installed code for canister low_wasm_memory_hook, with canister ID uxrrr-q7777-77774-qaaaq-cai
Deployed canisters.
URLs:
Backend canister via Candid interface:
low_wasm_memory_hook: http://127.0.0.1:4943/?canisterId=u6s2n-gx777-77774-qaaba-cai&id=uxrrr-q7777-77774-qaaaq-cai
After the deployment, the memory usage periodically increases as defined in the heartbeat
function.
The dfx canister update-settings
command sets the 'wasm_memory_limit' to 5MiB and 'wasm_memory_threshold' to 2MiB.
Hence, whenever the Wasm memory used by the canister is above 3MiB (in other words, the remaining Wasm memory is less than 'wasm_memory_threshold'), the low Wasm memory hook will be triggered.
This Motoko canister starts with ~2.3MiB of memory usage after the deployment, so it will trigger the low Wasm memory hook after allocating ~0.7MiB of memory.
You can verify that the canister settings got updated and check the current 'Memory Size' with the following command:
dfx canister status low_wasm_memory_hook
Example output:
Canister status call result for low_wasm_memory_hook.
Status: Running
Controllers: 3apfx-fn75o-xtwmf-svjzg-hu5xt-bg2dr-ubczq-uhvlq-2a5gf-ya4fn-dqe uqqxf-5h777-77774-qaaaa-cai
Memory allocation: 0 Bytes
Compute allocation: 0 %
Freezing threshold: 2_592_000 Seconds
Idle cycles burned per day: 24_269_759 Cycles
Memory Size: 2_374_914 Bytes
Balance: 2_996_231_412_893 Cycles
Reserved: 0 Cycles
Reserved cycles limit: 5_000_000_000_000 Cycles
Wasm memory limit: 5_000_000 Bytes
Wasm memory threshold: 2_000_000 Bytes
Module hash: 0x0c100162e1be161b9ef6fd95efb07f0541903c77a47e85a49a800705d6a09a11
Number of queries: 0
Instructions spent in queries: 0
Total query request payload size: 0 Bytes
Total query response payload size: 0 Bytes
Log visibility: controllers
Step 6: After a few seconds, observe the output of the
getExecutedFunctionsOrder
query:
Query the canister by calling getExecutedFunctionsOrder
to get the order of executed functions.
dfx canister call low_wasm_memory_hook --query getExecutedFunctionsOrder
Repeat the call until the last executed method is onLowWasmMemory
.
Example output:
(
vec { variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { heartbeat }; variant { onLowWasmMemory };},
)
To repeat the example, you can redeploy the canister and reset its state with the following command:
dfx deploy low_wasm_memory_hook --mode reinstall
Further learning
- Low memory hook in Motoko documentation
- Have a look at the locally running dashboard. The URL is at the end of the
dfx start
command:Dashboard: http://localhost:...
- Check out
low_wasm_memory_hook
canister's Candid user interface. The URLs are at the end of thedfx deploy
command:low_wasm_memory_hook: http://127.0.0.1:...
Canister interface
The low_wasm_memory_hook
canister provides the following interface:
getExecutedFunctionsOrder
; returns the vector with values ofFnType
(a variant with#heartbeat
or#onLowWasmMemory
) representing the order of functions executed.
Example usage:
dfx canister call low_wasm_memory_hook --query getExecutedFunctionsOrder
Resources
For more information take a look at low Wasm memory hook specification.
Security considerations and best practices
If you base your application on this example, we recommend you familiarize yourself with and adhere to the security best practices for developing on the Internet Computer. This example may not implement all the best practices.