首页 > 其他分享 >Minimizing Go WebAssembly Binary Size

Minimizing Go WebAssembly Binary Size

时间:2022-12-15 09:33:52浏览次数:62  
标签:WebAssembly TinyGo file Go Size my size

Minimizing Go WebAssembly Binary Size

https://dev.bitolog.com/minimizing-go-webassembly-binary-size/

 

Posted on October 9, 2020 by Omri Cohen Estimated reading time: 4 Minutes

 

In both of the previous posts I’ve described different aspects of WebAssembly. The first of the two explained what WebAssembly is and how to run a simple Go WebAssembly application in the browser. The second post was a Go WebAssembly performance benchmark. If you are unfamiliar with Go WebAssembly, I’d recommend reading the first post before diving into this one. In this post I’m going to discuss the Go WebAssembly binary size.

While working with Go WebAssembly I’ve noticed that the .wasm binary files are quite big. Not huge for my simple tests, but several MBs for a just a few functions. That made me ask myself – is that the best we can get assuming we want these files to be served over the web? In this blog post I’ll show you how to minimize your Go WebAssembly binary size so it will be much more web friendly.

Current State

Going back to my encoding example from the introductory post, you can see that the encode.wasm Go WebAssembly binary file size is roughly 2MB:

Current Go WebAssembly binary size

 

Currently the encoding function code imports only two packages:

import (
	"encoding/base64"
	"syscall/js"
)

 

If I was to import another package, let’s say the fmt package, how do you think that will affect the .wasm binary file size? let’s try it out:

Go WebAssembly binary size with when adding the fmt package

 

That’s a lot. Importing a simple and basic package such as fmt costs us roughly 0.4MB. A takeaway from this is that you need to keep in mind that packages imports leads to a larger binary file.

For the rest of this post, I’ll remove the fmt package and work with the original code.

First Try – Serving Gzipped Content

For my first attempt to reduce the .wasm file size, I ran my server with a gzip handler. This means that every file being served to the browser is first compressed using gzip on the server side, and extracted by the browser. You can read more about the method of serving compressed files here.

For the purpose of this test I used the gziphandler package in order to create a handler that compresses server responses:

package main

import (
	"github.com/NYTimes/gziphandler"
	"log"
	"net/http"
)

func main() {
	err := http.ListenAndServe(":8080",
		gziphandler.GzipHandler(http.FileServer(http.Dir("/path/to/served/files"))))
	if err != http.ErrServerClosed {
		log.Fatal(err)
	}
}

 

Now let’s see how much do we benefit by doing so:

Go WebAssembly binary size with when gzipped

 

Well this is not bad at all. Gzipping the content reduced the file size by about 75% from 2MB to 0.5MB. You can see that the time it takes to serve the file increased dramatically, that is because the gzip extraction process is more complex than simply serving static files.

Can we do it better?

Second Try – TinyGo

From the official homepage:

TinyGo is a project to bring the Go programming language to microcontrollers and modern web browsers by creating a new compiler based on LLVM.

[…] It can also be used to produce WebAssembly (WASM) code which is very compact in size.

TinyGo hompage – https://tinygo.org/

 

In other words – TinyGo is a Go compiler, focused on creating small binaries. Since TinyGo does not aim to compile any possible Go program, it lacks some language and packages support. In other words, this means that you might need to modify your code in order for it to be compiled by TinyGo.

Luckily for me, both of the packages my code imports are fully supported by TinyGo:

Now that we understand it’s purpose, let’s give it a try.

I chose to install TinyGo on my machine, you can also use a Docker image if you don’t want to install it locally. The official documentation on using TinyGo for WebAssembly is available here.

Compiling Using TinyGo

Now I needed to compile my main.go file to encode.wasm using the TinyGo compiler. This will replace the older 2MB file:

$ tinygo build -o encode.wasm -target wasm main.go

 

After creating the binary file, I then tried refreshing my browser session, only to get the following weird error:

Uncaught (in promise) TypeError: WebAssembly.instantiate(): Import #0 module="wasi_unstable" error: module is not an object or function

 

Well, turns out that the JavaScript glue code (which we talked about) used by the TinyGo compiler is a different one. So I had to replace it:

$ cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js .

 

Now refreshing worked, and so did my basic application!

Let’s take a look a the file size: **drums**

Go WebAssembly binary size with when compiled with TinyGo

 

Amazing! We got our .wasm binary file down from 2MB to 86KB.

Key Takeaways

  • Go WebAssembly is still in early stages but as you can see it’s quite ready to handle various use cases.
  • Decreasing the binary file size can be a bit tricky for larger applications but is feasible.
  • I would definitely recommend experimenting with this interesting technology which, in my opinion, we’ll see more and more of in the future as it matures.

 

As always, feel free to comment, like and share. See you on the next one!

标签:WebAssembly,TinyGo,file,Go,Size,my,size
From: https://www.cnblogs.com/jiftle/p/16984282.html

相关文章

  • MongoDB中执行批操作
    和大多数数据库系统类似,MongoDB也提供了api,支持在单个操作中插入或检索多个文档。通过减少客户端和MongoDB之间的交互次数,可以提高数据库的性能。使用.batchsize()优化批......
  • Go语言基础之函数
    函数函数是组织好的、可重复使用的、用于执行指定任务的代码块。Go语言中支持函数、匿名函数和闭包,并且函数在Go语言中属于“一等公民”。函数定义Go语言中定义......
  • django05
    目录django05一、模板层之标签1.if条件2.for循环二、自定义过滤器标签及inclusion_tag(了解知识)三、模板的继承与导入四、模型层之ORM常用关键字1.模型层之前期准备2.单......
  • Django之视图层
    视图函数视图层介绍一个视图函数,简称视图,是一个简单的Python函数,它接受Web请求并且返回Web响应。响应可以是一个HTML页面、一个404错误页面、重定向页面、XML......
  • django模型层详解
    django模型层详解自带的sqlate3数据库对时间字段不敏感有时候会展示错乱所以我们习惯切换成常见的数据库比如MYSQLdjangoorm并不会帮我们创建数据库所以需要我们自己......
  • Django之模板层
    Django之模板层目录Django之模板层模板语法传值模板层之标签自定义过滤器、标签及inclusion_tag模板的继承与导入模型层之前期准备ORM常用关键字模板语法传值方法一、#......
  • django框架模板层——标签、自定义过滤器、标签、inclusion_tag、继承与导入、外键字
    django框架模板层——标签、自定义过滤器、标签、inclusion_tag、继承与导入、外键字段、外键字段数据增删改查一、模板层之标签{%if条件1(可以是自己写的条件,也可以是......
  • Django框架:6、模型层之ORM查询关键字、SQL语句转换
    Django框架之模型层一、模型层前期准备介绍​ 在django框架中,模型层是直接和数据库进行操作的,所有数据的增删改查都由模型层来完成​ django框架自带的sqlite3数据库......
  • Django之模型层
    模型层之前期准备自带的sqlite3数据库对时间字段不敏感,有时候会展示错乱,所以我们习惯切换成常见的数据库比如MySQL,djangoorm并不会自动帮你创建库,所以需要提前准备好。D......
  • django之模型层
    目录模型层模型层前期准备模型层之ORM常见关键字模型层模型层前期准备使用djangoORM要注意​ 1、django自带的sqlite3数据可对时间字段不敏感,有时候会展示错乱,所以我......