Embedding JavaScript Engine in Go, a survey
tl;dr, results:
time | peak cpu% | peak mem | binary size | |
---|---|---|---|---|
native GO |
0.059s | 96% | 2,056 | 2.3M |
node fib.js |
0.157s | 97% | 22,752 | - |
Otto | 165.801s | 112% | 11,180 | 7.0M |
Duktape | 9.060s | 99% | 4,676 | 5.1M |
V8 | 0.108s | 99% | 12,676 | 13.0M |
—
GO programs are pre-compiled, so there is room for a run-time scripting language:
- Workflow/Job control scripting, rule engines
- Extensions/Plugins
- Application specific scripting (formulas/actions for non-technical users)
- Embedded hardware systems (where CI is hard, physical power is limited)
- Sand-boxed for run-time security
There are many to choose from:
- SQL
- Lua
- VBA
- Javascript
- Python
- roll your own
Why Javascript:
Doesn’t have to, but I am working on a project and I am fascinated by both the beauty and beast sides using PostgreSQL’s Javascript extension PL/V8.
Now the question is how?
Baseline #1, Javascript fib.js
1
2
3
4
5
6
function fib(n) {
if (n < 2) return n;
return fib(n - 2) + fib(n - 1);
}
console.log(fib(35));
Result:
Baseline #2, Native GO binary
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import "fmt"
func fib(n int) int {
if n < 2 {
return n
}
return fib(n-2) + fib(n-1)
}
func main() {
fmt.Println(fib(35))
}
Result:
Otto is a JavaScript parser and interpreter written natively in Go.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import (
"github.com/robertkrimen/otto"
)
func DiscardSendSync(msg string) string { return "" }
func main() {
vm := otto.New()
vm.Run(`
function fib(n) {
if (n < 2) return n;
return fib(n - 2) + fib(n - 1);
}
console.log(fib(35));
`)
}
Result:
Ducktape is an embeddable Javascript engine, with a focus on portability and compact footprint.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import (
"github.com/olebedev/go-duktape"
"log"
)
func main() {
ctx := duktape.New()
if err := ctx.PevalString(`
function fib(n) {
if (n < 2) return n;
return fib(n - 2) + fib(n - 1);
}
print(fib(35));
`); err != nil {
log.Fatal(err)
}
}
Result:
V8 is Google’s open source, high performance JavaScript engine. It is written in C++ and is used in Google Chrome.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
import (
v8 "github.com/ry/v8worker"
"log"
)
func DiscardSendSync(msg string) string { return "" }
func main() {
worker1 := v8.New(func(msg string) {
log.Println(msg)
}, DiscardSendSync)
err := worker1.Load("1.js", `
function fib(n) {
if (n < 2) return n;
return fib(n - 2) + fib(n - 1);
}
$print(fib(35));
`); err != nil {
log.Fatal(err)
}
}
Result: