Wasm module defined ___ globals which exceeds the maximum number allowed 200

When deploying my wasm, I am getting this error:

The invocation to the wallet call forward method failed with the error: 
An error happened during the call: 5: 
Wasm module of canister xxxxx-xxxxx-xxxxx-xxxxx-xxx is not valid: 
Wasm module defined 220 globals which exceeds the maximum number allowed 200.

What do these globals refer to ?

I am trying to figure out where they come from, so I can fix my code.

I am using C++, and I linked in a 3rd party json library that triggered this error.

Are they these things?

1 Like

Try to use ic-cdk-optimizer for wasm optimization (this is Rust utility from Dfinity)

Example of usage

# Install
curl https://sh.rustup.rs -sSf | sh # rust install
cargo install ic-cdk-optimizer

# Build your wasm from C++

ic-cdk-optimizer ./your-compiled-module.wasm -o ./your-awesome-compiled-module.wasm
1 Like

It made the wasm 37% smaller, but all the 220 globals remain.

Good tip though! I am going to include that optimizer in my build pipeline. Thank you.

1 Like

Cool! :slight_smile:
In that case, I can only advice to find a smaller library or move necessary code to your repo.

These arbitrary limits on the system on what should be internals of the canister can and probably should be adjusted. Different CDKs likely produce quite differently looking modules, and I assume the limit was chosen based on canisters in the wild, so mostly Rust and Motoko. If it turns out that C++ tends to use globals more heavily, then hopefully we can get the limit increased quickly.

(Or simply be lifted, as long as the cost of globals is adequately represented in the storage cost for a canister.)

Pinging @diegop , because this should probably trickle into the internal discussions.

2 Likes

Yeah, I was feeling the same way. The C++ code is working perfectly fine, but I cannot deploy it to IC due to this limit.

I am trying to find out where these globals come from, so I might be able reduce them, but I have not figured that out yet.

One guess may be function pointers across units of compilation. LLVM represents entries in something called Global Offset Table using globals. But my memory is vague and it’s late, so it might be something else.

There is some information in the note at

If you have some form of link-time-optimization that you can enable that might help?

Are these globals mutable or immutable? Ideally the system doesn’t store and thus charge for immutable globals, but I didn’t check.

What I am trying to do is link in a json library. I found a way to use C++ with std::string, so my thinking was that I now can use JSON data by using Candid text → std::string → JSON → do stuff → JSON → std::string → Candid text.

I tried 3 different versions, which all are pretty small & standalone:

I think that I need to stick to lower level C libraries for now, and wrap them myself into Classes that somehow do not generate globals. I am still studying what is generating these globals, but it does seem to be caused by function pointers, traits, virtual things & such…

1 Like

Im sure you are using WABT already, but if not there a lot of powerful tools for debugging these issues. Here is a wasm2wat online which can be useful: wasm2wat demo

1 Like

Yeah, I had already discovered WABT. Great tools indeed!

I am having good luck with cJSON, and can send json text back & forth. For now, this will work, but I will probably hit the globals limit again soon.

1 Like

@3cL1p5e7 ,
I have a follow-up question on ic-cdk-optimizer.

I added it to my github actions workflow, but the cargo install ic-cdk-optimizer step takes 7 minutes (!). I am using the ubuntu-latest runner.

I did some searching, but could not find a way to speed this up. Do you happen to know a trick?

Someone who knows rust well, correct me please

As I know, cargo can not download precompiled packages and compile crates directly on machine.
Nevertheless, you can try using github actions cache between jobs and put cargo caches there. More info about installed crates location
Here is another useful link with a similar problem