rogchap / v8go

Execute JavaScript from Go
https://rogchap.com/v8go
BSD 3-Clause "New" or "Revised" License
3.21k stars 221 forks source link

OOM after multiple calls (mac air M1) (go1.21.4 darwin/arm64) #397

Open loadgame opened 1 year ago

loadgame commented 1 year ago

main.go

package main

import (
    "log/slog"
    "runtime"

    "rogchap.com/v8go"
)

var ctx *v8go.Context

func runJavascript(script string) string {
    val, err := ctx.RunScript(script, "test.js")
    if err != nil {
        slog.Error("error", "val", val, "err", err)
    }
    return val.String()
}

func main() {
    ctx = v8go.NewContext()
    defer ctx.Close()
    runJavascript(`

        function test(jsonStr) {
            var jsonObj = JSON.parse(jsonStr);
            jsonObj.type = "test"
            var jsonStr = JSON.stringify(jsonObj);
            return jsonStr;
        }

    `)
    var res string
    for i := 0; i < 100000000; i++ {
        res = runJavascript(`test('{"value":"empty"}')`)
        if i%1000000 == 0 {
            slog.Warn("TestVM & golang GC", "res", res, "i", i)
            runtime.GC()
        }
    }
}

log below


023/11/15 20:25:22 WARN TestVM & golang GC res="{\"value\":\"empty\",\"type\":\"test\"}" i=18000000

<--- Last few GCs --->

[85430:0x130008000]    93664 ms: Mark-Compact 1377.1 (1442.6) -> 1363.5 (1445.1) MB, 801.6 / 0.0 ms  (average mu = 0.335, current mu = 0.213) allocation failure; scavenge might not succeed
[85430:0x130008000]    95239 ms: Mark-Compact 1380.9 (1446.6) -> 1367.5 (1449.1) MB, 1315.9 / 0.0 ms  (average mu = 0.239, current mu = 0.164) allocation failure; scavenge might not succeed

<--- JS stacktrace --->

#
# Fatal javascript OOM in Reached heap limit
#

SIGTRAP: trace trap
PC=0x104e36750 m=8 sigcode=0
signal arrived during cgo execution

goroutine 1 [syscall]:
runtime.cgocall(0x104e156b0, 0x1400005fcd8)
        /usr/local/go/src/runtime/cgocall.go:157 +0x44 fp=0x1400005fca0 sp=0x1400005fc60 pc=0x104d5f0f4
rogchap.com/v8go._Cfunc_ValueToString(0x37889ea80)
        _cgo_gotypes.go:2173 +0x3c fp=0x1400005fcd0 sp=0x1400005fca0 pc=0x104e107cc
rogchap.com/v8go.(*Value).String.func1(0x1400005fe08?)
        /Users/peter/go/pkg/mod/rogchap.com/v8go@v0.9.0/value.go:242 +0x60 fp=0x1400005fd70 sp=0x1400005fcd0 pc=0x104e12840
rogchap.com/v8go.(*Value).String(0x1400000e030?)
        /Users/peter/go/pkg/mod/rogchap.com/v8go@v0.9.0/value.go:242 +0x2c fp=0x1400005fe10 sp=0x1400005fd70 pc=0x104e126bc
main.runJavascript({0x105cce45d?, 0x19?})
        /vm_oom/main.go:17 +0xc4 fp=0x1400005fe90 sp=0x1400005fe10 pc=0x104e13114
main.main()
        /vm_oom/main.go:37 +0xc0 fp=0x1400005ff30 sp=0x1400005fe90 pc=0x104e13200
runtime.main()
        /usr/local/go/src/runtime/proc.go:267 +0x2bc fp=0x1400005ffd0 sp=0x1400005ff30 pc=0x104d9188c
runtime.goexit()
        /usr/local/go/src/runtime/asm_arm64.s:1197 +0x4 fp=0x1400005ffd0 sp=0x1400005ffd0 pc=0x104dbe784
krvajal commented 10 months ago

This seems to fix the issue

func runJavascript(script string) string {
    val, err := ctx.RunScript(script, "test.js")
    defer val.Release() // <= release the value
    if err != nil {
        slog.Error("error", "val", val, "err", err)
    }
    return val.String()
}