Skip to content

internal/wasmtools: run wasm-tools.wasm in embedded Wazero runtime - #252

Closed
Mossaka wants to merge 11 commits into
bytecodealliance:mainfrom
Mossaka:mossaka/wasmTools
Closed

Mossaka wants to merge 11 commits into
bytecodealliance:mainfrom
Mossaka:mossaka/wasmTools

Conversation

@Mossaka

@Mossaka Mossaka commented Nov 28, 2024 •

Copy link
Copy Markdown
Member
  • add wasm-tools as git submodule
  • update Makefile to compile wit/wasm-tools.wasm
  • use wazero to execute wasm-tools.wasm

what I did to optmize the wasm-tools Wasm binary size

The current wasm-tools.wasm size is 3.5M

  1. Cargo.toml setup
[profile.release]
lto = true # compile with link-time optimization
codegen-units = 1 # compile with a single codegen unit
opt-level = "z" # optimize for size
panic = "abort" # panic=abort will remove the panic code
strip = true # strip the debug information
  1. disable default features and only added "component" feature
wasm-tools = { version = "1.221.0", default-features = false, features = [
	"component",
]}
  1. gzip compress it

Let me know if you know more ways to cut down the size of the binary!

Comment thread .gitmodules Resolved
Comment thread Makefile Outdated
.PHONY: $(wit_files)
$(wit_files):
wasm-tools component wit -j --all-features $@ > $@.json
$(wit_files): wit/wasm-tools.wasm

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put the Wazero and wasm-tools dependency into internal/ or x/.

As it stands, this creates a new problem where consumers of package cm will have an implicit dependency on Wazero. We need to figure out a way around this.

Comment thread wit/wasmtools.go Resolved
Comment thread wit/wasm-tools.wasm Resolved
Comment thread wit/testdata_test.go Resolved
Comment thread internal/wasmtools/wasmtools.go Outdated

// Executor is an interface for running Wasm modules.
type Executor interface {
Run(ctx context.Context, args []string, stdin io.Reader, fsMap map[string]string) (stdout *bytes.Buffer, stderr *bytes.Buffer, err error)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be an fs.FS?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you referring to the fsMap? yes it can be defined as map[fs.FS]string

Comment thread Makefile Resolved
Comment thread Makefile Resolved
Comment thread internal/wasmtools/.gitignore Resolved
Comment thread internal/wasmtools/wasmtools.go Resolved
}
config = config.WithFSConfig(fsConfig)

_, err = w.runtime.InstantiateModule(ctx, w.module, config)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this run in a goroutine?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. I've added a 10s timeout to it so that it won't run forever.

WithSysWalltime().
WithArgs(append([]string{"wasm-tools.wasm"}, args...)...)
if name != nil {
config = config.WithName(*name)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the name arg necessary?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in the test.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of the name? Does it matter to the caller?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to run wasm-tools.wasm multiple times, the Run() would fail without the name parameter because the wazero module configuration defaults the "name" to what was decoded from the name section and duplicate names are not allowed in a single Runtime.

Comment thread internal/wasmtools/wasmtools.go Outdated
return w.runtime.Close(ctx)
}

func (w *WasmTools) Run(ctx context.Context, args []string, stdin io.Reader, fsMap map[string]string, name *string) (stdout *bytes.Buffer, stderr *bytes.Buffer, err error) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of fsMap map[string]string, how about a varadic dirs ...string at the end of the argument list?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you not want to distinguish host and guest paths?

If we use dirs ...string we will have to set the guest path as the same as the host path. i.e. fsConfig.WithDirMount(dir, dir)

Comment thread internal/wasmtools/wasmtools.go Resolved
Comment thread internal/wasmtools/wasmtools.go Resolved
@ydnar

ydnar commented Dec 11, 2024

Copy link
Copy Markdown
Collaborator

I think we’ll need to add build tags to disable this functionality when run under TinyGo (e.g. have Run always return nil, nil, error).

@ydnar ydnar changed the title Run wasm-tools as Wasm file in embedded wazero runtime internal/wasmtools: run wasm-tools.wasm in embedded Wazero runtime Dec 11, 2024
@Mossaka
Mossaka marked this pull request as ready for review December 11, 2024 06:48
Comment thread wit/wit_test.go Resolved
@Mossaka
Mossaka requested a review from ydnar December 12, 2024 05:43
Comment thread internal/wasmtools/types.go Resolved
@ydnar

ydnar commented Dec 15, 2024

Copy link
Copy Markdown
Collaborator

@Mossaka can you rebase and squash some commits?

* add wasm-tools as git submodule
* update Makefile to compile wit/wasm-tools.wasm
* use wazero to execute wasm-tools.wasm
* Makefile: add a build command
* Commit the wasm-tools.wasm file
* Makefile: replace path with a variable for the name of the target
* wit, Makefile: move wasmtools.go to internal/wasmtools
* Remove wasmtools submodule

Signed-off-by: Jiaxiao Zhou (Mossaka) <duibao55328@gmail.com>
Adding lto, opt-level=z and other options to the cargo.toml reduces the wasm-tools.wasm binary size from 7.8 MBi to 3.5 MBi

Signed-off-by: Jiaxiao Zhou (Mossaka) <duibao55328@gmail.com>
Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
…map[fs.FS]string

Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
…ve naming

* Rename to WasmTools to Instance
* Add build tags to disable wasmtools when run under TinyGo
* wasmtools_tinygo: New returns a new error
* Rename Executor to Runner

Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
… in TinyGo

Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
…nce API

Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
@Mossaka

Mossaka commented Dec 15, 2024

Copy link
Copy Markdown
Member Author

Added more docs and updated CHANGELOG

…m and update Makefile

This adds gzip compression for the wasm-tools.wasm to further reduce the size to 1.2M from 3.5M.
Added the wasm file to the .gitignore and thus the remote repo will only have the gzip file.
Updated Makefile to zip and unzip the Wasm module.

Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>
Signed-off-by: Jiaxiao Zhou <duibao55328@gmail.com>

@ydnar ydnar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the propose of the gzip code? Groundwork for gzipping the binary output?

go-version-file: go.mod

- name: Set up wams-tools.wasm
run: make internal/wasmtools/wasm-tools.wasm

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to do this?

The artifact should already be committed, and this adds a Rust dependency / build step to the release workflow.

)

//go:embed wasm-tools.wasm
var wasmTools []byte

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be the gz file?

version: ${{ env.wasm-tools-version }}

- name: Set up wams-tools.wasm
run: make internal/wasmtools/wasm-tools.wasm

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary?

Should we delete the step above?

with:
version: ${{ env.wasm-tools-version }}

- name: Set up wams-tools.wasm

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Necessary? Delete this and the step above?

@ydnar

ydnar commented Dec 15, 2024

Copy link
Copy Markdown
Collaborator

Had an idea: internal/cmd/wasm-tools-go that wraps internal/wasmtools with a CLI. No need to have Wasmtime installed.

@ydnar

ydnar commented Dec 18, 2024

Copy link
Copy Markdown
Collaborator

Implemented in #272

@Mossaka

Mossaka commented Dec 18, 2024

Copy link
Copy Markdown
Member Author

Close for #272

@Mossaka Mossaka closed this Dec 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants