Wasm module exceeding maximum allowed functions

Fair enough. I suppose the next best thing would be to at least suggest this in our documentation in case users encounter such issues.

@borovan I would be curious to see what happens if you use the IC CDK optimizer on your wasm binary. Actually, it should be quite similar because it’s using the same underlying binary I think.

That’s just using binaryen right? I dont think I can take any more wasm tonight hah. Need booze.

If you compile an empty Motoko file you’ll probably see a lot in there before you even start adding your own code.

Some info on why is here:

1 Like

Have you looked at SudoDB/Sudograph?

I suspect that with a little bit of work you might be able to define loadMany, loadRange, create, and update, etc. once and then provide the entity as an argument to them.

That would reduce the number of functions significantly, and it wouldn’t continue to grow as you add more entities.

Something like this:

import Time "mo:base/Time";

type Proxy<A> = {
  #Proxy;
};

module Rarity {
  public type Entity = {
    // ...
  };
  
  public type Metadata = {
    createdAt : Time.Time;
  };
  
  public type Record = {
    name : Text;
  };
  
  public let proxy : Proxy<(Entity, Metadata, Record)> = #Proxy;
};

module Other {
  public type Entity = {
    otherEntityField : Text;
  };
  
  public type Metadata = {
    otherMetadataField : Text;
  };
  
  public type Record = {
    otherRecordField : Text;
  };
  
  public let proxy : Proxy<(Entity, Metadata, Record)> = #Proxy;
};

// Fake Query implementation
class Query<Entity, Metadata, Record>(/*caller : _, store : _, path :_*/) {
  public func loadMany(ids : [Nat]) : [Entity] {
    return [];
  }
};

func loadMany<E, M, R>(proxy : Proxy<(E, M, R)>, ids : [Nat]) : [E] {
  Query<E, M, R>().loadMany(ids);
};

let rarityEntities : [Rarity.Entity] = loadMany(Rarity.proxy, [0, 1, 2, 3]);
let otherEntities : [Other.Entity] = loadMany(Other.proxy, [0, 1, 2, 3]);

Or forget about the wrapper and update Query to take the proxy instead.

I had a look on that but for our use case is way too unevolved.

We have a lot of moving parts like custom validators based on multiple inputs with complex logic behind it, sanitisers, multiple transaction types.

As an alternative to wasm-opt, you can also try this tool:

I think it uses the Rust walrus library to actually do the optimization.

Not sure about how well tested this is though.

One caveat with all these optimizers is that they won’t optimize any actor classes used by your code (since the wasm for those classes is embedded in the client, and won’t be recognized as wasm by the tools).

In the long term, our best be would be to tightly integrate one of these tools into the Motoko compiler, or implement our own tree-shaking pass.

Thanks, yeah this is awesome. Already started on a solution like this and we’re down around 3300 funcs with the optimiser.

Just a bit of a shame that the number of functions seems to be a much lower barrier than anything else… we’re ok for now anyway.

1 Like