Skip to content

Performance #85

Open
Open
@mariotoffia

Description

@mariotoffia

Hi, I'm new to extism but find your project very attractive! Thanks!

I wonder what to expect in terms of performance, and is there a way to improve that?

I'm using tinygo to compile the was file using tinygo build -o <outfile> -target wasi <gofile>

I've done two benchmarks:

  1. Noop Function

Noop function:

//export hello_world_noop
func helloWorldNoop() int32 {
	return 0
}

Host benchmark:

func BenchmarkNoopFunction(t *testing.B) {
	wasm, err := cbwasm.CompileGoWasmToBytes("testdata/plugins/hello_world/main.go")
	require.NoError(t, err)

	manifest := extism.Manifest{
		Wasm: []extism.Wasm{
			extism.WasmData{Name: "hello_world_noop", Data: wasm}},
	}

	ctx := context.Background()
	config := extism.PluginConfig{
		EnableWasi: true,
	}

	plugin, err := extism.NewPlugin(ctx, manifest, config, []extism.HostFunction{})
	require.NoError(t, err)

	t.ResetTimer()

	for i := 0; i < t.N; i++ {
		_, _, err = plugin.CallWithContext(ctx, "hello_world_noop", nil)
		require.NoError(t, err)
	}
}

Output:

goos: darwin
goarch: arm64
cpu: Apple M1 Pro
BenchmarkNoopFunction-10    	  170604	      7429 ns/op	   70157 B/op	      23 allocs/op
PASS
  1. Passing large JSON array

plug-in:

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

//export arr_json_benchmark
func arrJsonBenchmark() int32 {
	var input []Person

	if err := pdk.InputJSON(&input); err != nil {
		pdk.SetError(err)
		return -1
	}

	if err := pdk.OutputJSON(input); err != nil {
		pdk.SetError(err)
		return -1
	}

	return 0
}

Host benchmark:

func BenchmarkSerializeMuchJsonData(t *testing.B) {
	wasm, err := cbwasm.CompileGoWasmToBytes("testdata/plugins/json_test/main.go")
	require.NoError(t, err)

	manifest := extism.Manifest{
		Wasm: []extism.Wasm{extism.WasmData{Name: "arr_json_benchmark", Data: wasm}},
	}

	ctx := context.Background()
	config := extism.PluginConfig{EnableWasi: true}

	plugin, err := extism.NewPlugin(ctx, manifest, config, []extism.HostFunction{})
	require.NoError(t, err)

	var (
		data    []byte
		count   int = 1000
		compare []byte
	)

	data = append(data, []byte("[")...)
	for i := 0; i < count; i++ {
		data = append(data, []byte(fmt.Sprintf(`{"name":"John Doe","age":%d},`, count))...)
	}

	data = append(data[:len(data)-1], []byte("]")...)

	compare = data

	t.ResetTimer()

	for i := 0; i < t.N; i++ {
		exit, out, err := plugin.Call("arr_json_benchmark", data)
		require.NoError(t, err)
		require.Equal(t, uint32(0), exit)
		require.Equal(t, compare, out)
	}
}

Output (Native is just go std json.Unmarshal/Marshal for comparison):

goos: darwin
goarch: arm64
cpu: Apple M1 Pro
BenchmarkSerializeMuchJsonDataNative-10    	    3133	    377033 ns/op	  101108 B/op	    1019 allocs/op
BenchmarkSerializeMuchJsonData-10          	     222	   5015298 ns/op	  151928 B/op	      30 allocs/op

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions