rogchap / v8go

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

Question: How to transfer large objects between go and v8 with high performance? #405

Open zbysir opened 7 months ago

zbysir commented 7 months ago

My need is to transfer large objects between golang and v8. Usually it has a size of 1M (after Json serialization). I tested using v8.JSONParse() and it will take about 4ms (for 1M json). Is there any way to improve the transfer performance?

Here are some simpler examples and what I tried:

var sampleData = `{
    "root": {
        "id": "lZRRDONbpAi",
        "vid": "lZRRDONbpAi",
        "type": "breakpoint"
    },
    "abc": {
        "id": 1,
        "age": 2
    }
}`

// 3,229 ns/op
func BenchmarkJSONSample(b *testing.B) {
    ctx := v8.NewContext()
    for i := 0; i < b.N; i++ {
        v8.JSONParse(ctx, sampleData)
    }
}

Next I tried initializing the value directly using the v8 api instead of serialization

func toValue(iso *v8.Isolate, pt *v8.ObjectTemplate, ctx *v8.Context, v any) *v8.Value {
    switch v.(type) {
    case string,
        int32,
        uint32,
        int64,
        uint64,
        bool,
        float64:
        x, err := v8.NewValue(iso, v)
        if err != nil {
            panic(err)
        }
        return x
    case map[string]any:
        obj, _ := pt.NewInstance(ctx)
        for k, v := range v.(map[string]any) {
            obj.Set(k, toValue(iso, pt, ctx, v))
        }

        return obj.Value
    default:
        panic(fmt.Sprintf("unsupported type: %T", v))
    }
}
// 18,634 ns/op
// On the contrary, it is slower. I guess it is because c needs to be called multiple times.
func BenchmarkToValueSample(b *testing.B) {
    v := map[string]interface{}{}
    json.Unmarshal([]byte(sampleData), &v)
    ctx := v8.NewContext()
    ot := v8.NewObjectTemplate(ctx.Isolate())
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        toValue(ctx.Isolate(), ot, ctx, v)
    }
}

Is there any way to improve the transfer performance?

I don't know much about cgo vs v8, maybe I'm missing some available API?