2019-12-09 Weekend Learnings

December 9, 2019 • edited April 10, 2020

I discovered that Go supports build to Web Assembly. What a great time to be alive. Also I’ve spent some time changing the favicon of this blog and finished the post about Python Jupyter notebook with Plotly

So one weekend more and now I can say that I’ve generated Web Assembly. Just the fact that Go can be compiled into WASM is incredible because it means that one day we will be able to write everything with the amazing Go syntax and run everywhere.

I’ve been following this tutorial that explains how to do a hello world in WASM. I’ve modified it to run my Mandelbrot code in the browser and guess what. It actually works! The modifications are really simple. I took the test code used for benchmarks and modified it to return the jpg image encoded as base64. I’ve set the number of Areas to 1, this is because WASM doesn’t support multithread applications so there is no advantage in splitting the calculation over multiple goroutines.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func mandelbrotDraw(this js.Value, i []js.Value) interface{} {
	pic := mandelbrot.NewPicture(complex(-1.401854499759, -0.000743603637), 0.00021646*1024, 1024, 1, 1000)
	var err error
	pic.Init()
	result, err := Calculate(100, 1, pic)
	if err != nil {
		log.Panic(err)
	}

	buf := &bytes.Buffer{}

	encodingError := jpeg.Encode(buf, result, &jpeg.Options{Quality: 90})
	if encodingError != nil {
		panic(err)
	}
	return js.ValueOf(
		b64.StdEncoding.EncodeToString(buf.Bytes()),
	)
}

The javascript code is really simple. Just call the mandelbrotDraw function and set the image.src to the value returned. I’ve added timing information to measure the performance.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function draw(a, b) {
	startTime = new Date();
	data = mandelbrotDraw(a, b)
	endTime = new Date();
	var timeDiff = endTime - startTime; 
	console.log(timeDiff/1000.0 + " seconds");

	img = document.getElementById("img")
	img.src = 'data:image/jpeg;base64,' + data
}

First, I ran this in Firefox, because is my default browser. The result is that the mandelbrot image is rendered in 6.743s. Well… the go version of this render takes 1.111s. So there is a clear problem of performance. Before throwing everything away and wait a few years before this is improved. I’ve read somewhere that the performance of WASM is highly dependent on the browser. So I decided to try in Chrome. It took 1.576s to render the image. AMAZING! Sayonara, JavaScript.

For fun, I loaded the page in my phone browser and it took about 10s. Not bad.

Check out the full code in the mandelbrot repository under cmd/mandelbrot-wasm in the mandelbrot-wasm branch

blogweekendgo

2019-12-15 Weekend Learnings

Python Jupyter Notebook With Plotly Support