Easiest way to know when canister size gets to certain size

Hi all!

I want to know what is the easiest way of checking current canister size in the code itself of that canister so that I can know when is the time to either:

  1. Stop receiving further calls that add more data to it (to prevent issues with canister size getting too large, which would cause issues in upgrades etc)
  2. Branch off from that canister to a fresh new canister with the same codebase but empty data

Is there an easy way of just setting a “MAX_CANISTER_SIZE” Nat and then checking against that in any method that would try and add more data to it?

In Motoko you can use Prim.rts_memory_size() and in Rust it seems to be memory_size in core::arch::wasm32 - Rust .

Have a look at this thread for more details: Motoko, Array, Memory

This repo does this in Rust:

and there might be other examples in the following thread: ICDevs.org Bounty #20 - QuickStart Dapp - Scaling With Canisters - 200 ICP, 100 ICP, 50 ICP - Multiple winners

1 Like

Thank you very much :slight_smile: I’ve seen this in another thread around the forum as well, but it was said that it’s a “risk” using it since it may change in the future. How viable would this be to use for a platform that would probably get in trouble if this stops working at a certain point and there were already hundreds of deployed smart contracts from the “factory” contract deploying them using now obsolete code for checking the storage? Would it be a terrible (or impossible task) of upgrading code later on in these “auto-deployed” contracts if this happens?

Please take a look at how we are getting memory size at Canistergeek (motoko and rust):

2 Likes

Thanks Alexey! I wanted to mention Canistergeek but forgot.

Good question. I’ll forward this internally.

1 Like

Thank you for this, I didn’t know such service exists :slight_smile: To me, it seems like this tool provides measurements for how much data a specific canister implementing this library is using at specific time during the day? So, since I just need to know this info at any method that might store more data into the canister, I would just need to use Prim.rts_memory_size() that your library also uses in the above collectMemory() method and check against the MAX_CANISTER_SIZE variable that I can set initially in the canister as the largest size of the canister I want to allow? Something like:

let MAX_CANISTER_SIZE: Nat = 2_000_000_000; // this would be approx 2GB of storage?
  public query func someMethodThatWouldWantToStoreMoreData(data: Blob): async Text {
    if(Prim.rts_memory_size() < MAX_CANISTER_SIZE) {
      // we can do further checks for the passed in data to see if it's size + Prim.rts_memory_size is still smaller than MAX_CANISTER_SIZE and error out if not

      // if all is good, we can add new data to the contract here
    } else {
      // we return the error
    }
  }

Or am I completely missing something here? :slight_smile:

I chatted with @dsarlis about this. There is a risk, but the risk is essentially that there are non-backwards compatible changes to WASM, since we are not building our own WASM runtime but use the one developed by the Byte Code Alliance. The risk for this seems to be rather low.

Yep, with two comments:

  1. Your example is a query, so would not allow to store data anyway :wink: . If you’re mostly concerned with data from outside the IC you could (additionally) use the inspect_message hook to check for this without having to spend cycles.

  2. You might want to make MAX_CANISTER_SIZE changeable via some form of administrative action, since upgrades to the system could allow to safely increase the limit.

1 Like

Thank you very much for the confirmation :slight_smile: Sorry, I just used some sample method that I doodled real quick to make it into a pseudo code, did not even see it’s a query method :smiley: Could you just explain a bit more on the quote ? What’s the inspect_message, never seen it before, is it a part of one of the core ICP libraries or something else?

Sure, your canister can use this hook to decide if it wants accept an ingress message or deny it without going through consensus.

Here’s how you do it in Rust: inspect_message in ic_cdk_macros - Rust

In Motoko the feature was only recently exposed: Release 0.6.28 · dfinity/motoko · GitHub

1 Like

Very nice, ty good ser! All of this will be very useful :slight_smile: Thank you both

1 Like