Precompiled modules
View Sourceserialize/1 turns a compiled module into Wasmtime's precompiled form, and
deserialize/1 loads that form without compiling. You need it when compile
time matters at start-up (the 30 MB CPython module takes about 350 ms to
compile and 4 ms to deserialize from its 17 MB precompiled form) or when the
machine that runs modules should not carry the compiler at all.
Compile once, at build time
{ok, Bin} = file:read_file("python.wasm"),
{ok, Mod} = wasmtime:compile(Bin),
{ok, Pre} = wasmtime:serialize(Mod),
ok = file:write_file("python.cwasm", Pre).Load at run time
{ok, Pre} = file:read_file("python.cwasm"),
{ok, Mod} = wasmtime:deserialize(Pre),
{ok, Inst} = wasmtime:instantiate(Mod, ...).The module behaves exactly like one from compile/1: same exports, same
options, same instances.
Keep a cache
load(WasmPath) ->
Cache = WasmPath ++ ".cwasm",
case file:read_file(Cache) of
{ok, Pre} ->
case wasmtime:deserialize(Pre) of
{ok, Mod} -> {ok, Mod};
{error, _} -> compile_and_cache(WasmPath, Cache)
end;
_ ->
compile_and_cache(WasmPath, Cache)
end.
compile_and_cache(WasmPath, Cache) ->
{ok, Bin} = file:read_file(WasmPath),
{ok, Mod} = wasmtime:compile(Bin),
{ok, Pre} = wasmtime:serialize(Mod),
ok = file:write_file(Cache, Pre),
{ok, Mod}.A stale cache (other Wasmtime version, other CPU features) fails
deserialize/1 with class => compile and falls through to a fresh compile.
Compile options and compatibility
A precompiled module records how it was compiled. At load time Wasmtime compares that with the engine:
| Option | Checked at load | So |
|---|---|---|
fuel | yes, exactly | load with deserialize(Bin, #{fuel => true}) (deserialize/1 tries it too) |
opt_level | no | loads on any engine, including runtime-only builds; the code keeps the level it was compiled at |
proposals | as a subset | a module compiled with proposals disabled loads on the defaults |
module_options/1 on the compile side tells you what to pass on the load
side.
Notes
- The precompiled form is tied to the Wasmtime version in
scripts/wasmtime.versionand to the CPU features of the machine that produced it. Wasmtime checks both and refuses a mismatch. - It contains machine code. Wasmtime verifies the header, not the code, so
deserialize/1must only ever see bytes that came fromserialize/1on a machine you trust. Never deserialize input from a user; give users.wasmfiles andcompile/1, which validates everything. - The bytes are not a WebAssembly module:
compile/1rejects them, anddeserialize/1rejects a.wasmfile. - A node that only ever loads precompiled modules can be built without the
compiler:
WASMTIME_RUNTIME_ONLY=1 rebar3 compile, 4 MB instead of 25. See building, "Runtime-only builds".