cmd/tsconnect: run wasm-opt on the generated wasm file

Saves about 1.4MB from the generated wasm file. The Brotli size is
basically unchanged (it's actually slightly larger, by 40K), suggesting
that most of the size delta is due to not inlining and other changes
that were easily compressible.

However, it still seems worthwhile to have a smaller final binary, to
reduce parse time and increase likelihood that we fit in the browser's
disk cache. Actual performance appears to be unchanged.

Updates #5142

Signed-off-by: Mihai Parparita <mihai@tailscale.com>
pull/6066/head
Mihai Parparita 2 years ago committed by Mihai Parparita
parent 2a9ba28def
commit d60f7fe33f

@ -216,10 +216,41 @@ func buildWasm(dev bool) ([]byte, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("Cannot build main.wasm: %w", err) return nil, fmt.Errorf("Cannot build main.wasm: %w", err)
} }
log.Printf("Built wasm in %v\n", time.Since(start)) log.Printf("Built wasm in %v\n", time.Since(start).Round(time.Millisecond))
if !dev {
err := runWasmOpt(outputPath)
if err != nil {
return nil, fmt.Errorf("Cannot run wasm-opt: %w", err)
}
}
return os.ReadFile(outputPath) return os.ReadFile(outputPath)
} }
func runWasmOpt(path string) error {
start := time.Now()
stat, err := os.Stat(path)
if err != nil {
return fmt.Errorf("Cannot stat %v: %w", path, err)
}
startSize := stat.Size()
cmd := exec.Command("../../tool/wasm-opt", "-Oz", path, "-o", path)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil {
return fmt.Errorf("Cannot run wasm-opt: %w", err)
}
stat, err = os.Stat(path)
if err != nil {
return fmt.Errorf("Cannot stat %v: %w", path, err)
}
endSize := stat.Size()
log.Printf("Ran wasm-opt in %v, size dropped by %dK\n", time.Since(start).Round(time.Millisecond), (startSize-endSize)/1024)
return nil
}
// installJSDeps installs the JavaScript dependencies specified by package.json // installJSDeps installs the JavaScript dependencies specified by package.json
func installJSDeps() error { func installJSDeps() error {
log.Printf("Installing JS deps...\n") log.Printf("Installing JS deps...\n")
@ -256,7 +287,7 @@ func setupEsbuildTailwind(build esbuild.PluginBuild, dev bool) {
} }
cmd := exec.Command(*yarnPath, yarnArgs...) cmd := exec.Command(*yarnPath, yarnArgs...)
tailwindOutput, err := cmd.Output() tailwindOutput, err := cmd.Output()
log.Printf("Ran tailwind in %v\n", time.Since(start)) log.Printf("Ran tailwind in %v\n", time.Since(start).Round(time.Millisecond))
if err != nil { if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok { if exitErr, ok := err.(*exec.ExitError); ok {
log.Printf("Tailwind stderr: %s", exitErr.Stderr) log.Printf("Tailwind stderr: %s", exitErr.Stderr)

@ -0,0 +1,74 @@
#!/bin/sh
#
# This script acts like the "wasm-opt" command from the Binaryen toolchain, but
# uses Tailscale's currently-desired version, downloading it first if necessary.
set -eu
BINARYEN_DIR="$HOME/.cache/tailscale-binaryen"
read -r BINARYEN_REV < "$(dirname "$0")/binaryen.rev"
# This works for Linux and Darwin, which is sufficient
# (we do not build for other targets).
OS=$(uname -s | tr A-Z a-z)
if [ "$OS" = "darwin" ]; then
# Binaryen uses the name "macos".
OS="macos"
fi
ARCH="$(uname -m)"
if [ "$ARCH" = "aarch64" ]; then
# Binaryen uses the name "arm64".
ARCH="arm64"
fi
install_binaryen() {
BINARYEN_URL="https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_REV}/binaryen-version_${BINARYEN_REV}-${ARCH}-${OS}.tar.gz"
install_tool "wasm-opt" $BINARYEN_REV $BINARYEN_DIR $BINARYEN_URL
}
install_tool() {
TOOL=$1
REV=$2
TOOLCHAIN=$3
URL=$4
archive="$TOOLCHAIN-$REV.tar.gz"
mark="$TOOLCHAIN.extracted"
extracted=
[ ! -e "$mark" ] || read -r extracted junk <$mark
if [ "$extracted" = "$REV" ] && [ -e "$TOOLCHAIN/bin/$TOOL" ]; then
# Already extracted, continue silently
return 0
fi
echo ""
rm -f "$archive.new" "$TOOLCHAIN.extracted"
if [ ! -e "$archive" ]; then
log "Need to download $TOOL '$REV' from $URL."
curl -f -L -o "$archive.new" $URL
rm -f "$archive"
mv "$archive.new" "$archive"
fi
log "Extracting $TOOL '$REV' into '$TOOLCHAIN'." >&2
rm -rf "$TOOLCHAIN"
mkdir -p "$TOOLCHAIN"
(cd "$TOOLCHAIN" && tar --strip-components=1 -xf "$archive")
echo "$REV" >$mark
}
log() {
echo "$@" >&2
}
if [ "${BINARYEN_DIR}" = "SKIP" ] ||
[ "${OS}" != "macos" -a "${OS}" != "linux" ] ||
[ "${ARCH}" != "x86_64" -a "${ARCH}" != "arm64" ]; then
log "Unsupported OS (${OS}) and architecture (${ARCH}) combination."
log "Using existing wasm-opt (`which wasm-opt`)."
exec wasm-opt "$@"
fi
install_binaryen
"$BINARYEN_DIR/bin/wasm-opt" "$@"
Loading…
Cancel
Save