Wasmer: What's in a wasmer_serialized_module_t?

Created on 1 Jul 2020  ·  8Comments  ·  Source: wasmerio/wasmer

In the C API, when I compile a wasmer_module_t and then serialize it into a wasmer_serialized_module_t, is this machine code or just the internal representation of the module that still needs to be interpreted or JITed? How much compilation happens to transform the wasm code into the wasmer_module_t? How much loading time would be saved if I precompile and serialize a wasmer_serialized_module_t as part of my build, vs loading the wasm code at runtime?

❓ question

All 8 comments

is this machine code or just the internal representation of the module that still needs to be interpreted or JITed?

Once we have a serialized module, there is no more compilation happening at runtime, only loading and linking.

How much compilation happens to transform the wasm code into the wasmer_module_t?

When creating a module we:

  • Generate the metadata of the module (how many globals, functions, tables and memories has the module, for example)
  • Compile the wasm functions to machine code
  • Generate the signature trampolines (so you can call a wasm function very easily)

That way, when you serialize the module, you serialize all the compiled functions, wasm metadata and trampolines, so the effort needed for loading it is minimal (just pushing the functions into memory and deserialize the metadata).

We are working on making loading wasm serialized code at runtime super optimal. So loading a wasm module would be as fast as doing a dlopen on a shared library (order of nanoseconds). Stay tuned!

Ok, cool. That sounds like exactly what I'm after.

@syrusakbary do you have any plans to partition wasmer_serialized_module_t representation into two parts: data and code? Current API seems to mix everything together into a single "bytes" container, which does not seem to support environments where OS prevents you from directly mapping executable memory (e.g. iOS). For such environments you want to have something like:

wasmer_result_t wasmer_serialized_module_from_bytes(wasmer_serialized_module_t **serialized_module,
                                                    const uint8_t *serialized_module_data_bytes,
                                                    uint32_t serialized_module_bytes_data_length,
                                                    const uint8_t *serialized_module_code_bytes,
                                                    uint32_t serialized_module_bytes_code_length);

(and similarly serialization should produce byte arrays objects).

@mraleph definitely. That's something we are very open on having, if it helps on fulfilling your use case.
We are now on the process of refactoring Wasmer, the good news is that it will make super easy splitting data and code (and even creating custom serialized formats for the binary), so the implementation of an split wasmer_serialized_module_from_bytes would be trivial.

We are also planning on targeting iOS and have some ideas for it in mind 🙂.
Feel free to reach me to [email protected], it might be a bit easier to setup a Google Meet and chat online!

I looked at how things work right now - and it does indeed seem like there should be some changes in the implementation before it becomes useful in an iOS setting. Current setup seems to be compiler backend specific and it is the compiler backend that is tasked with loading the serialized module - e.g. if you use LLVM as Wasmer backend then you use llvm::object::ObjectFile and llvm::RuntimeDyld to load the result. This is not going to work on iOS - the loading would need to go through the system dynamic loader and not through the custom (LLVM) one.

That's completely on point.

One of the things that we are doing with the refactor is separating the compilation process from the serialization/loading of artifacts. This will make super easy to make your use case work.
The refactor will land into the main repo sometime in the next two weeks, we can probably follow-up here right after :)

@mraleph we just merged the refactor a few weeks ago, and it now allows to have custom ways for serializing/deserializing via custom engines.

That should make super easy to solve the problem you commented:

wasmer_result_t wasmer_serialized_module_from_bytes(wasmer_serialized_module_t **serialized_module,
                                                    const uint8_t *serialized_module_data_bytes,
                                                    uint32_t serialized_module_bytes_data_length,
                                                    const uint8_t *serialized_module_code_bytes,
                                                    uint32_t serialized_module_bytes_code_length);

Let us know if we can provide any help to showcase how to create such engine!

Closing the issue for now.

Let me know if you have any questions and we will answer/reopen as needed :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

robinvanemden picture robinvanemden  ·  5Comments

CuriousTommy picture CuriousTommy  ·  4Comments

ensch picture ensch  ·  5Comments

repi picture repi  ·  3Comments

danchitnis picture danchitnis  ·  4Comments