Skip to content

Commit

Permalink
Merge pull request #2248 from ulan/ulan/resource-reservation
Browse files Browse the repository at this point in the history
Add docs about the resource reservation mechanism
  • Loading branch information
ulan authored Dec 5, 2023
2 parents a41f539 + a508e61 commit 4791556
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
20 changes: 20 additions & 0 deletions docs/developer-docs/gas-cost.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,23 @@ The following table shows the calculated storage cost per GB for a 30-day month:
| | | 13-node Application Subnets | 34-node Application Subnets |
|----------------------|------------------------------------|-----------------------------|-----------------------------|
| GB Storage Per Month | For storing a GB of data per month | $0.431 | $1.127 |

## Resource reservation mechanism

In order to encourage long-term usage and discourage spiky usage patterns of resources, the Internet Computer uses a *resource reservation mechanism* that was adopted by the community in [NNS proposal 12604](https://dashboard.internetcomputer.org/proposal/126094).
Every time a canister allocates new storage bytes, the system sets aside some amount of cycles from the main balance of the canister. These reserved cycles are used to cover future payments for the newly allocated bytes. The reserved cycles are not transferable and the amount of reserved cycles depends on how full the subnet is. For example, it may cover days, months, or even years of payments for the newly allocated bytes.

The operations that allocate new bytes are:

- Wasm instruction: `memory.grow`.
- System API calls: `ic0.stable_grow()` `ic0.stable64_grow()`.
- Increasing the `memory_allocation` in canister settings.

These operations reserve some amount of cycles by moving them from the main balance of the canister to the reserved cycles balance.
The amount of reserved cycles depends on how many bytes are allocated and on the current subnet usage:

- If subnet usage is below `450GiB`, then the amount of reserved cycles per allocated byte is `0`.
- If subnet usage is above `450GiB`, then the amount of reserved cycles per allocated byte grows linearly depending on the subnet usage from `0` to `10` years worth of storage payments at the subnet capacity (which is currently `750GiB`).

A controller of a canister can disable resource reservation by setting the `reserved_cycles_limit=0` in canister settings.
Such opted-out canisters would not be able to allocate if the subnet usage is above `450GiB` though.
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ Compute allocation: 0
Freezing threshold: 2_592_000
Memory Size: Nat(2363181)
Balance: 3_100_000_000_000 Cycles
Reserved: 0 Cycles
Reserved Cycles Limit: 5_000_000_000_000 Cycles
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
```

Expand Down Expand Up @@ -196,6 +198,8 @@ Compute allocation: 0
Freezing threshold: 2_592_000
Memory Size: Nat(2363181)
Balance: 3_100_000_000_000 Cycles
Reserved: 0 Cycles
Reserved Cycles Limit: 5_000_000_000_000 Cycles
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
```

Expand All @@ -220,7 +224,7 @@ To check a canister's cycles balance, you must be the controller of the canister
dfx canister status 5o6tz-saaaa-aaaaa-qaacq-cai --network ic
```

The output will resemble the following, where the value `Balance` refers to the cycles balance:
The output will resemble the following, where the value `Balance` refers to the main cycles balance and `Reserved` refers to the reserved cycles balance:

```
Canister status call result for 5o6tz-saaaa-aaaaa-qaacq-cai.
Expand All @@ -231,6 +235,8 @@ Compute allocation: 0
Freezing threshold: 2_592_000
Memory Size: Nat(2363181)
Balance: 3_100_000_000_000 Cycles
Reserved: 0 Cycles
Reserved Cycles Limit: 5_000_000_000_000 Cycles
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
```

Expand All @@ -249,6 +255,40 @@ There are a few ways to top up a canister:

This tutorial will cover the first two workflows. For more information on using a third-party service for cycles management, please see [here](../../../developer-docs/setup/cycles/cycles_management_services).


## Setting the reserved cycles limit

When a canister allocates storage bytes, the system may reserve some amount of cycles by moving them from the main cycles balance of the canister to the reserved cycles balance.
These reserved cycles are used for future storage payments as explained [here](../../../developer-docs/gas-cost#resource-reservation-mechanism).

You can control the maximum amount of reserved cycles by setting the reserved cycles limit:

```sh
dfx canister update-settings 5o6tz-saaaa-aaaaa-qaacq-cai --reserved-cycles-limit 42 --network ic
dfx canister status 5o6tz-saaaa-aaaaa-qaacq-cai --network ic
```

The first command sets the reserved cycles limit to `42` and the second command queries the canister status and shows the following output:

```
Canister status call result for 5o6tz-saaaa-aaaaa-qaacq-cai.
...
Reserved: 0 Cycles
Reserved Cycles Limit: 42 Cycles
...
```

Once the reserved cycles balances reaches the reserved cycles limit, the system is going to fail all operations that require cycle reservation.
The error message might look like this:

```
Canister cannot grow memory by 65536 bytes due to its reserved cycles limit. The current limit (42) would be exceeded by 1000.
```

Such errors can be fixed by increasing the reserved cycles limit.


### Using ICP

If you currently have a balance of ICP tokens within your dfx ledger account ID, you can use the `dfx ledger top-up` command to automatically convert that ICP into cycles and deposit it into the specified canister, for example:
Expand Down

0 comments on commit 4791556

Please sign in to comment.