Canister Optimizer available in dfx 0.14.0

Wasm-opt: A general purpose WASM optimizer available in dfx now

I’m excited to announce the integration of wasm-opt, a general purpose wasm optimizer, into dfx.

You can enable optimizations in your dfx.json like so:

{
  "canisters": {
    "my_canister": {
      "optimize": "cycles"
    }
  }
}

You can check out the specific numbers here: Enable wasm optimizer from `dfx 0.14.0` by kentosugama · Pull Request #55 · dfinity/canister-profiling · GitHub

As a rough estimate, you can expect to see improvements in cycle usage of Motoko canisters by around 10% and Rust canisters by around 7%. Further, your binary sizes should be reduced by roughly 16%.

More Details

The optimizations are provided by wasm-opt, an open source wasm optimizer that is wrapped by ic-wasm to make it compatible with IC canisters.

ic-wasm exposes a couple options for optimization that you can enable from dfx.json. “cycles” is the recommended default, which maps to optimization level 3 in wasm-opt. If you want to aggressively reduce binary size instead, you can do so with the “size” option.

Optimization levels for cycle usage:

  • O4
  • O3 (equivalent to “cycles”)
  • O2
  • O1
  • O0 (performs no optimizations)

Optimization levels for binary size:

  • Oz (equivalent to “size”)
  • Os

Our benchmarking indicates that O3 outperforms O4. This is most likely due to the fact that wasm-opt is optimizing for bare-metal execution speed (considering the cache hierarchy for example) while performance on the IC is calculated by the number of instructions executed.

These optimizations preserve the IC specific metadata sections of your canisters. Furthermore, if you want to preserve the name sections in your wasm module, you can directly invoke ic-wasm (instead of enabling optimizations in dfx) with the --keep-name-section flag.

Also, note that in certain cases the optimizations can increase the complexity of certain functions in your wasm module such that they are rejected by the replica. If you run into this issue, we recommend using a less aggressive optimization level such that you do not exceed the complexity limit.

Feedback welcome

We appreciate any feedback on the optimizer as you guys try it out! I hope that all that happens are some free performance gains, but if you encounter any issues please let us know.

16 Likes

These are great numbers, Kento! Thanks for being persistent and getting this in. Meanwhile the Motoko team is working on some nice improvements to cycle usage for high allocation scenarios. (I hope teasing is allowed…)

Stay tuned for the upcoming moc releases, those should be especially exciting in combination with this new ic-wasm feature!


But a word of warning: wasm-opt is a product of a different team and thus contributes a bit more to your trusted computing base. Bugs in it may cause problems (possibly in corner cases only) with moc-generated code, so be sure to DYOR and test!

3 Likes

after adding this do I need to use ic-wasm explicitly or if I already use ic-wasm this thing isn’t necessary…

If I understand your question correctly, if you enable the option in your dfx.json file, you do not need to do anything else.

Just wanted to check, if you don’t set the optimize property in dfx.json, there is no optimization performed by dfx.json right?

For canister type custom, you either need to specify optimize or shrink. Rust and Motoko get shrinked automatically. Source

1 Like